2016-05-11 10 views
0

私はMongoを介して "メッセージ"を渡している2つの.Net(C#)アプリケーションを持っています。 1つはライター、もう1つはリーダーです。 _tタイプのディスクリミネータは、デシリアライズで問題を引き起こしています。MongoDBドライバでの動的型2.2 - _t型ディスクリミネータをシリアル化しない方法は?

これは、それらが通信に使用している一般的なクラスの簡略化されたバージョンの通りである:ライタアプリケーションが実際にその意志他のタイプの値の上にマッピングすることによってMyMessageのインスタンスを作成して

public class MyMessage { 
    public long Id {get; set;} 
    public string MessageText {get; set;} 
    public dynamic OriginalObject{get; set;} 
} 

リーダーアプリには不明です。既知の共通要素をマップし、元のオブジェクト全体を動的OriginalObjectプロパティに割り当てます。

public MyMessage CreateMessage(SomeOtherType originalMsg) { 
    return new MyMessage { 
     MessageText = originalMsg.SomeField, 
     OriginalObject = originalMsg    
    }; 
} 

ネットMongoのドライバは、MyMessageをシリアル化は、OriginalObjectサブ文書へ_t型識別器を追加します。

ただし、Readerアプリには、Writerのすべてのタイプの参照はありません。 リーダーアプリケーションがMyMessageを逆シリアル化しようとすると、OriginalObjectのタイプには、Unknown discriminator valueのエラーが発生します。

実際のタイプが公称タイプと一致しないときは常に、_tタイプのディスクリミネータが追加されています。そして、それは真の多形的で強く型付けされたシナリオで意味があります。しかし、C#に動的な型定義があるので、私はそれを使いたいと思います。

また、のインスタンスMyMessage.OriginalMessageは純粋に匿名のタイプですが、完全に動作します。いいえ_tタイプのdiscriminatorが書き込まれます。 Readerアプリは、それを動的(expando)オブジェクトとしてうれしく逆シリアル化し、すべてが機能します。 OriginalMessageのインスタンスが私がこの問題を抱えている強いタイプです。

ダイナミックタイプに_tタイプのディスクリミネータを追加しないようにMongoドライバに指示するにはどうすればよいですか? 私はまた、他のソリューション/回避策にも興味がありますが、_tを除いて、私の好ましいアプローチになります。

.Net Framework 4.6.1、MongoDB.Driver 2.2。3

よりサンプルコード:

public void SaveMessages() 
{ 
    var message1 = new MyMessage { 
     Id=1, 
     MessageText="Anonymous Message", 
     OriginalMessage=new{ Field1 = "f1", Field2 = "f2" } 
    }; 
    _collection.InsertOne(message1); // no _t since OriginalMessage is purely anonymous 

    var message2 = new MyMessage { 
     Id=2, 
     MessageText="Strong Message", 
     OriginalMessage=new SomeOtherType{Prop1="p1", Prop2="p2"} 
    }; 
    _collection.InsertOne(message2); // has _t since SomeOtherType is not "dynamic" 
} 
+0

あなたは「BsonDocument」を試す代わりに「ダイナミック」しましたか? – Soren

+0

MyMessage定義をBsonDocumentのような強力な型を使用するように変更するだけで問題ありません。しかし、私は実際には、その特定のタイプ(たとえその特定のタイプがBson/Json/Dictionaryのような柔軟性があっても)を、 – JoeG

答えて

0

あなたはこのように、フェッチ中の項目を除外するためにProjectを使用することができます。

return await this.GetCollection() 
      .Find(filter: new BsonDocument("_id", handle)) 
      .Project(Builders<BsonDocument>.Projection.Exclude("_t")) 
      .FirstAsync(); 
0

少し遅れてパーティーに、しかし、ここで無効にする大会ですdiscriminatorsの書き込み:

internal class NoDiscriminatorConvention : ConventionBase, IClassMapConvention 
{ 
    public void Apply(BsonClassMap classMap) 
    { 
     classMap.SetDiscriminatorIsRequired(false); 
    } 
} 

あなたはあなたのアプリのスタートアップに登録することができます歌う:

ConventionRegistry.Register("No discriminators for message types", 
     new ConventionPack { new NoDiscriminatorConvention() }, 
     type => typeof(MyMessage).IsAssignableFrom(type)); 

すでに例えば、MyMessageクラスをマッピングしている場合MongoDBのの_id要素としてIdプロパティを使用するために、あなたはすぐそこにそれを行うことができます。

BsonClassMap.RegisterClassMap<MyMessage>(cm => { 
    cm.MapIdMember(m => m.Id).SetSerializer(new StringSerializer(BsonType.ObjectId)); 
    cm.AutoMap(); 
    cm.SetDiscriminatorIsRequired(false); }); 
関連する問題