1

Mongoと公式のC#ドライバーを使用するアプリケーションを構築しています。インターフェイスとジェネリック型の制約を使用すると、奇妙な問題が発生します。次のことを考慮してください。

interface IMongoObject
{
    BsonObjectId Id { get; set; }
    string Name { get; set; }
}

class MongoObject : IMongoObject
{
    public BsonObjectId Id { get; set; }
    public string Name { get; set; }
}

class Program
{
    MongoServer m_db;
    string m_dbName;

    protected void Save<T>(T entity) where T : IMongoObject
    {
        GetDatabase().GetCollection<T>(typeof(T).Name).Save(entity);
    }

    protected T Get<T>(string name) where T : IMongoObject
    {
        Type t = typeof(T);

        // Throws
        return GetDatabase().GetCollection<T>(typeof(T).Name).AsQueryable().Where(o => o.Name == name).FirstOrDefault();
    }

    protected MongoDatabase GetDatabase()
    {
        if (m_db == null)
        {
            var conString = "mongodb://localhost/MongoTest";
            MongoUrl url = new MongoUrl(conString);
            m_dbName = url.DatabaseName;
            m_db = MongoServer.Create(url);
        }

        return m_db.GetDatabase(m_dbName);
    }

    void Run()
    {
        MongoObject o = new MongoObject();
        o.Name = "Foo";
        Save(o);

        MongoObject b = Get<MongoObject>("Foo");
        Console.ReadKey();
    }

    static void Main(string[] args)
    {
        Program p = new Program();
        p.Run();
    }
}

Get(...)の呼び出しを除いて、すべてが正常に機能します。var memberSerializationInfo = containingSerializationInfo.Serializer.GetMemberSerializationInfo(memberName);公式ドライバーを使用すると、SelectQuery.csの関数の呼び出しからnull参照例外が発生しますprivate BsonSerializationInfo GetSerializationInfoMember(IBsonSerializer serializer, MemberExpression memberExpression)

LINQにFluentMongoを使用するように切り替えると、次のようなメッセージが表示されます。

「ディスクリミネーターはクラスにのみ登録でき、インターフェイスMyLib.Services.IRepoDataには登録できません。」

これは基本的にこの男と同じです:

FluentMongoが突然エラーをスローする

IMongoObjectが何であるかを知らないため、Mongoドライバーが文句を言っていることを理解しています。私が理解していないのは、where呼び出し内の式が「o」をMongoObjectタイプではなくIMongoObjectタイプとして認識している理由です(デバッガーでこれが起こっていることを確認しました)。

抽象基本クラスの使用に切り替えると、すべて正常に機能します。すべての「MongoObjects」がそうではないので、私はこれを何をすべきかわからない

ありがとう

4

1 に答える 1

0

したがって、問題は実際には、C#コンパイラがオブジェクトの式ツリーをどのようにまとめているかにあります。タイプの制約により、NameプロパティにアクセスするときにMongoObjectをIMongoObjectにキャストしています。したがって、IMongoObjectは式のタイプであり、IMongoObjectでメンバーを見つけることができません。次のバージョンのドライバーでこの状況に対してできることがあるかどうかを確認しますが、今のところ、抽象クラスに固執します。

別の注意点として、「ドメイン」オブジェクトをDTOと混在させないことが最善の場合があります。代わりに、各責任に1つずつ、2つ用意し、それらの間でマップします。

--UPDATE--興味深いメモ。どうやら、これは、VB.NETがc#とは異なる方法で式ツリーを作成する方法に関する別の問題に基づいて修正されています。したがって、近い将来、これは正しく機能します。これを証明するテストは、https ://github.com/craiggwilson/mongo-csharp-driver/commit/153b9862b122521eee681a86e56806d94fed8b21#diff-1で確認できます。

于 2012-04-24T13:25:05.790 に答える