2016-04-03 7 views
1

私はIDとObjectKey、または同じオブジェクトであってもよいランダム値とオブジェクトを比較しようとしています。要するに、オブジェクトを、同じ型だけでなく、何かと比較したいのです。'obj == value'を 'obj.Equals(value)'に変更するためにExpressionVisitorを使用してください

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

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

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

最後に、誰かが将来どこでも '=='を使用する可能性があるため、すべてのクエリを手動で変更することはできません。

私はExpressionVisitorに来ました。私は私のLinqクエリの式を書き換えることができることに気づいたが、私はまあまあだ。私は見つけたいくつかの例を試しましたが、何らかのエラーがあります。

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

がこれを置き換える: するvarオブジェクト= ctx.Where(OBJ => OBJ ==値)。

to this: var objects = ctx.Where(obj => obj.Equals(value));

可能ですか?

答えて

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); 
    } 
} 

これらのすべての出力に:

オリジナル: 名=>(((名前== "AA")OrElse(name.Length < 0))OrElse(名前= "! B "))に変換

: 名=>((name.Equals(" AA ")OrElse(name.Length < 0))OrElseない(name.Equals(" B ")))

0

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

"LinqKit"がリライタでAsExpandableと一緒に使用するアプローチを実行することもできます。このアプローチはずっと簡単ですが、これらの呼び出しを各クエリに挿入する必要があります。

また、Roslynを使用してソースコードを1回リファクタリングすることもできます。その欠点は、ソースコードがEquals呼び出しではあまりうまく見えなくなることです。

多くの作業があるため、これらのソリューションをスケッチするのに必要な時間はありません。 AsExpandableの場合、ウェブ上で作業コードを見つけることができます。私はLINQプロバイダを書くためのチュートリアルもあると確信しています。

関連する問題