5

次のAPIを備えたサードパーティのライブラリがあります。

 Update<TReport>(object updateOnly, Expression<Func<TReport,bool>> where)

私がやりたいのは、このメソッドを呼び出すことですが、次のような匿名オブジェクトを使用します。

Update(new {Name = "test"}, new {Id = id})

2番目の匿名オブジェクトを取得して次のようなものに変換することは可能ですか?

x => x.Id == id.

だから私が欲しいのは、新しい{Id = id}をTReportを受け取り、boolを返す関数に変換することですか?

4

2 に答える 2

2

物事を複雑にしているという事実についてダニエル・A・ホワイトに同意したとしても、私は少し試してみました。

しかし、それは安全ではありませんlosing strong typing。(匿名オブジェクトには好きなものを入れることができます。オブジェクトの「実際の」プロパティにリンクされていません。したがって、リファクタリングやチェックはありません...)

それは実際にはテストされていないので、それがあなたが望むものであるかどうかはわかりません。「述語オブジェクト」には、(機能する場合は)さまざまなオブジェクトを含めることができます。

new {Name="test"}, new{Id=1, Name="test2"})

だから、あなたはそのようなものを持つことができます:

public static class MyHelpers
{
        public static Expression<Func<TReport, bool>> CreatePredicate<TReport>(this object predicateObject)
        {
            var parameterExpression = Expression.Parameter(typeof(TReport), "item");
            Expression memberExpression = parameterExpression;
            var objectDictionary = MakeDictionary(predicateObject);
            foreach (var entry in objectDictionary.Where(entry => typeof(TReport).GetProperty(entry.Key) == null))
            {
               throw new ArgumentException(string.Format("Type {0} has no property {1}", typeof(TReport).Name, entry.Key));
            }
            var equalityExpressions = GetBinaryExpressions(objectDictionary, memberExpression).ToList();
            var body = equalityExpressions.First();
            body = equalityExpressions.Skip(1).Aggregate(body, Expression.And);

            return Expression.Lambda<Func<TReport, bool>>(body, new[] { parameterExpression });
        }
        private static IDictionary<string, object> MakeDictionary(object withProperties)
        {
            var properties = TypeDescriptor.GetProperties(withProperties);
            return properties.Cast<PropertyDescriptor>().ToDictionary(property => property.Name, property => property.GetValue(withProperties));
        }

        private static IEnumerable<BinaryExpression> GetBinaryExpressions(IDictionary<string, object> dic, Expression expression)
        {
            return dic.Select(m => Expression.Equal(Expression.Property(expression, m.Key), Expression.Constant(m.Value)));
        }
}

使用法、例えば

public void Update<TReport>(object updateOnly, object predicateObject) {
   var predicate = predicateObject.CreatePredicate<TReport>();
   yourGenericApi.Update(updateOnly, predicate);
}

編集:強いタイピングセキュリティを失っているので、次のようなものを追加する必要があります

foreach (var entry in objectDictionary.Where(entry => typeof(TReport).GetProperty(entry.Key) == null))
{
    throw new ArgumentException(string.Format("Type {0} has no property {1}", typeof(TReport).Name, entry.Key));
}

var objectDictionary = MakeDictionary(predicateObject);
于 2012-08-02T12:10:19.613 に答える
0

関数に返したい特定の値がある場合は、次のように簡単に実行できると思います。

bool desiredResult = true;
Update(new { Name = "test" }, x => desiredResult);
于 2012-08-02T11:06:08.583 に答える