2017-01-26 53 views
1

のC#MongoDbシリアル化イベントをログに記録するデータベースにコレクションがあります。各タイプのイベントには、異なるデータセットがあります。私はこれを次のクラスで定義しました:辞書の文字列、オブジェクト>

[CollectionName("LogEvent")] 
public class LogEvent 
{ 
    public LogEvent(string eventType) 
    { 
     EventType = eventType; 
     EventData = new Dictionary<string, object>(); 
    } 

    public string EventType { get; private set; } 
    [BsonExtraElements] 
    public IDictionary<string, object> EventData { get; private set; } 
} 

これはかなりうまくいきます。限りEventData辞書の要素は単純型であるとして...

var event = new LogEvent("JobQueues"){ 
    EventData = new Dictionary<string, object>(){ 
     { "JobId": "job-123" }, 
     { "QueueName": "FastLane" } 
    } 
} 

_mongoCollection.InsertOne(event); 

...私は

{ 
    _id: ObjectId(...), 
    EventType: "JobQueued", 
    JobId: "job-123", 
    QueueName: "FastLane" 
} 

しかし、すぐに私はカスタム型を追加しようとしてのようなMongoの文書を入手します辞書は、動作が停止します。

var event = new LogEvent("JobQueues"){ 
    EventData = new Dictionary<string, object>(){ 
     { "JobId": "job-123" }, 
     { "QueueName": "FastLane" }, 
     { "JobParams" : new[]{"param-1", "param-2"}}, 
     { "User" : new User(){ Name = "username", Age = 10} } 
    } 
} 

これは私が[BsonExtraElements]タグを削除し、[BsonDictionaryOptions(DictionaryRepresentation.Document)]場合、それはエラーなしでシリアル化のものを開始しますが、それは私が好きではない完全な別の文書を与える私に".NET type ... cannot be mapped to BsonType."

のようなエラーが発生します。 。私が欲しいもの

{ 
    _id: ObjectId(...), 
    EventType: "JobQueued", 
    EventData: {  
     JobId: "job-123", 
     QueueName: "FastLane", 
     User: { 
     _t: "User", 
     Name: "username", 
     Age: 10 
     }, 
     JobParams : { 
     _t: "System.String[]", 
     _v: ["param-1", "param-2"] 
     } 
    } 
} 

、以下の結果である:

{ 
    _id: ObjectId(...), 
    EventType: "JobQueued", 
    JobId: "job-123", 
    QueueName: "FastLane", 
    User: { 
    Name: "username", 
    Age: 10 
    }, 
    JobParams : ["param-1", "param-2"] 
} 

これを達成する方法を知っている人はいますか?

(私はC#のmongodriver v2.3デベロッパーを使用しています)

答えて

0

、それをバックdeserilizeするタイプの情報を必要とするためのでMongoDriverは、動作します。起動プログラムに

public class CustomUserMapper : ICustomBsonTypeMapper 
{ 
    public bool TryMapToBsonValue(object value, out BsonValue bsonValue) 
    { 
     bsonValue = ((User)value).ToBsonDocument(); 
     return true; 
    } 
} 

どこか: は、あなたが何ができるか、書き込み、Userクラスのための独自のCustomMapperを登録することである

BsonTypeMapper.RegisterCustomTypeMapper(typeof(User), new CustomUserMapper()); 

がうまくいく、と私は、正確なデータをシリアル化するために管理していますあなたが望むように。

しかし:あなたが戻ってそれを非直列化すると、ドライバがそれをデシリアライズするhiowに関する情報を持っていませんので、あなたは、DictionaryとしてあなたUserクラスを取得ウィルは:

enter image description here

+0

デシリアライズは問題ではありません。これは「追加のみ」のコレクションであり、何かが読まれるまれな状態では、それはカスタム投影によるものです。 とにかくカスタムシリアライザは良いオプションではありません。これは、ログに「何でも」を追加できることです。 – Vegar

+0

私はまずjson.netでデータをシリアル化し、json.netのbsondocumentを作成するようにmongoに依頼することで回避策を講じました。それはちょっとうまくいったが、最適な解決策ではなかった。 – Vegar

+0

@Vegarおそらくあなたの回避策が最良の解決策であろう。 MongoDriveはどんなものでもコレクションに追加できますが、正確にSAMフォームに戻すことが可能であることを確実にしたいと思っています。そのためにはtypedescriptorsを使用しています。 –

関連する問題