物事を複雑にしているという事実についてダニエル・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);