2016-04-17 23 views
2

私の特定のシナリオでは、レコードを検索するためのSQL文を動的に構築します。これは、ビジネスサービス層のWebApiでサーバー側で行われます。今度は、この機能を拡張して、WHERE節をクライアント側でも設定できるようにします。強く型付けして、クライアント上で列名をハードコードしないようにしたいと思います。ラムダ式パラメータを取得する方法

これまでのところ、私は次のようでした:

1)INFORMATION_SCHEMAからビューの列を取得し、列の値は、後の段階で設定されるようにDictionary<string, object>を埋めます。カスタムクラスに変更して、column_name = column_valueの代わりに比較フィールドを追加することができます。

public class CustomerSearchDto 
{ 
    [SearchColumn(Name = "customer_type")] 
    public CustomerType CustomerType { get; set; } 

    [SearchColumn(Name = "city")] 
    public string City { get; set; } 

    public CustomerSearchDto() 
    { } 
} 

3)だから、クライアントに、今私が行うことができます:

2)私は、カスタム属性と私がクライアントに公開するだけで検索カラムを含むクラスを作成しました

//Following line is pseudo-code 
var predicate = (x => x.CustomerType == CustomerType.Private); 

このラムダ式を使用し、(1)の列リストを持ち、(2)の列名を知っている場合、辞書の対応する列の値を設定するにはどうすればよいですか?

答えて

0

あり、あまりにも多くの仮定がありますが、あなたはこのような何かを始めることができます:

static void SetValue<T>(Dictionary<string, object> target, Expression<Func<T, bool>> predicate) 
{ 
    var comparison = predicate.Body as BinaryExpression; 
    Debug.Assert(comparison != null); 
    var member = (comparison.Left.NodeType == ExpressionType.Convert ? 
     ((UnaryExpression)comparison.Left).Operand : 
     comparison.Left) as MemberExpression; 
    Debug.Assert(member != null); 
    var value = comparison.Right as ConstantExpression; 
    Debug.Assert(value != null); 
    var attribute = Attribute.GetCustomAttribute(member.Member, typeof(SearchColumnAttribute)) as SearchColumnAttribute; 
    var columnName = attribute?.Name ?? member.Member.Name; 
    var columnValue = value.Value; 
    target[columnName] = columnValue; 
} 

テスト:代わりに辞書とそのからクエリを構築するの

Expression<Func<CustomerSearchDto, bool>> predicate = (x => x.CustomerType == CustomerType.Private); 
var dict = new Dictionary<string, object>(); 
SetValue(dict, predicate); 
0

、あなたが行くことができますExpressionVisitorを使用して書き直すことにより、クライアント側の式からSQL式への変換を1ステップで実行できます。

ExpressionVisitorは、適切な方法を無効にします。 protected override Expression VisitMember(MemberExpression node)であり、そのメソッドの内部では、クライアント側のフィールド名をサーバー側のフィールド名に変換します。

クライアント側をシリアライズし、サーバー側をデシリアライズする問題はありますが、一度使用すればビジターを使用してSQL用に書き直すことができます。

関連する問題