1

オブジェクトをIDである可能性のあるランダムな値とObjectKey、または同じオブジェクトと比較しようとしています。要するに、オブジェクトを同じ型だけでなく、何でも比較したいのです。

これを行うために、オブジェクトの Equals() と GetHashCode() をオーバーライドしましたが、期待どおりに動作しています。しかし、「obj == value」で検索すると、Linq がこれらのメソッドを呼び出さないことに気付きました。

クエリを「obj.Equals(value)」に変更すると、Equals() メソッドが呼び出されます。しかし、それは私が必要とするものではありません。

さらに、「==」および「!=」演算子をオーバーロードしようとしましたが、インターフェイスを介して検索しているため、これらのオーバーロードは呼び出されていません。

最後に、すべてのクエリを手動で変更することはできません。誰かが将来どこでも「==」を使用してコードを壊す可能性があるからです。

だから私は ExpressionVisitor に来ます。Linq クエリの式を書き直すことができることに気付きましたが、ちょっと無知です。見つけたいくつかの例を試しましたが、何らかのエラーが発生しました。

最後に、これが ExpressionVisitor 経由で必要なものです。

これを置き換えます: var objects = ctx.Where(obj => obj == value);

これに: var objects = ctx.Where(obj => obj.Equals(value));

出来ますか?

4

2 に答える 2

0

これは可能です。式を書き換えた後、クエリを実際のプロバイダーに渡すプロキシ クエリ プロバイダーを作成できます。

「LinqKit」のリライタを使ったアプローチを追求することもできますAsExpandable。このアプローチははるかに簡単ですが、これらの呼び出しを各クエリに挿入する必要があります。

Roslyn を使用して、ソース コードの 1 回限りのリファクタリングを実行することもできます。Equalsその欠点は、これらの呼び出しでソース コードの見栄えが低下することです。

これらのソリューションは大変な作業であるため、これらのソリューションをスケッチするのに必要な時間がありません。AsExpandableウェブ上で動作するコードを見つけることができます。LINQ プロバイダーを作成するためのチュートリアルもあるはずです。

于 2016-04-03T21:33:45.840 に答える
0

わーい。それを見つけた:

class Program
{
    static void Main(string[] args)
    {
        //the sample:
        Expression<Func<string, bool>> expr = name => name == "AA" || name.Length > 0 || name != "b";
        Console.WriteLine(expr);
        EqualsModifier treeModifier = new EqualsModifier();
        Expression modifiedExpr = treeModifier.Modify((Expression)expr);
        Console.WriteLine(modifiedExpr);
        Console.ReadLine();
    }
}
//the ExpressionVisitor
public class EqualsModifier : ExpressionVisitor
{
    public Expression Modify(Expression expression)
    {
        return Visit(expression);
    }
    protected override Expression VisitBinary(BinaryExpression b)
    {
        if (b.NodeType == ExpressionType.Equal)
        {
            Expression left = this.Visit(b.Left);
            Expression right = this.Visit(b.Right);
            MethodInfo equalsMethod = typeof(string).GetMethod("Equals", new[] { typeof(string) });
            return Expression.Call(left, equalsMethod, right);
        }
        else if (b.NodeType == ExpressionType.NotEqual)
        {
            Expression left = this.Visit(b.Left);
            Expression right = this.Visit(b.Right);
            MethodInfo equalsMethod = typeof(string).GetMethod("Equals", new[] { typeof(string) });
            return Expression.Not(Expression.Call(left, equalsMethod, right));
        }
        return base.VisitBinary(b);
    }
}

これらはすべて次のように出力されます。

オリジナル: name => (((name == "AA") OrElse (name.Length < 0)) OrElse (name != "b"))

変換: name => ((name.Equals("AA") OrElse (name.Length < 0)) OrElse Not(name.Equals("b")))

于 2016-04-04T22:40:43.503 に答える