我有第三方库,其中包含以下API:
Update<TReport>(object updateOnly, Expression<Func<TReport,bool>> where)
我想要做的是调用此方法但使用匿名对象,例如:
Update(new {Name = "test"}, new {Id = id})
是否可以获取第二个匿名对象并将其转换为类似:
x => x.Id == id.
所以我想要的是将新的{Id = id}转换为一个接受TReport并返回bool的函数?
答案 0 :(得分:2)
即使我同意丹尼尔·A·怀特(Daniel A. White)的说法,因为事情变得复杂,我还是试了一下。
但这不安全,因为你是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);
答案 1 :(得分:0)
如果你有一个特定的值,你希望函数返回,我想你可以这样做:
bool desiredResult = true;
Update(new { Name = "test" }, x => desiredResult);