[英]Create an expression that will evaluate the result of a delegate and return the consequent or the alternate as the case may be
我想使用getter表達式檢索屬性的值,但是在該表達式中,我想評估一個謂詞,並且僅當謂詞評估為false時才返回該屬性的值,否則返回一個常量。
遵循以下原則(部分使用此處的代碼):
Expression<Func<U, bool>> exp = FuncToExpression(predicate);
var instance = Expression.Parameter(propertyInfo.DeclaringType, "instance");
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, typeof(object));
var getLamba = Expression.Lambda(convert, instance);
var evaluate = Expression.Condition(exp, getLamba, Expression.Constant(alternate));
var lambda = Expression.Lambda(evaluate, instance);
return (Func<T, object>)lambda.Compile();
這里的任何幫助將不勝感激
編輯
根據喬恩的評論更詳細:
我在評估變量上遇到以下錯誤:{“參數必須為布爾值”}
這是FuncToExpression
方法:
private static Expression<Func<U, bool>> FuncToExpression<U>(Func<U, bool> predicate)
{
return argument => predicate(argument);
}
編輯2
完整樣本:
public class Test
{
public static void Main(string[] args)
{
TestPredicate test = new TestPredicate();
test.Number = 11;
Func<TestPredicate, object> callDelegate;
PropertyInfo info = typeof(TestPredicate).GetProperties().Where(a => a.Name == "Number").FirstOrDefault();
Func<int, bool> f = (x => x > 10 ? true : false);
if (info != null)
{
callDelegate = CreateValueGetDelegate<TestPredicate, int, int>(info, f, -1);
var item = (int) callDelegate(test);
Console.WriteLine(item); // expecting -1 here
}
Console.Read();
}
private static Func<T,object> CreateValueGetDelegate<T,U, S>(PropertyInfo propertyInfo, Func<U, bool> predicate, S alternate)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
Expression<Func<U, bool>> exp = FuncToExpression(predicate);
var instance = Expression.Parameter(propertyInfo.DeclaringType, "instance");
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, typeof(object));
var getLamba = Expression.Lambda(convert, instance);
var evaluate = Expression.Condition(exp, getLamba, Expression.Constant(alternate));
var lambda = Expression.Lambda(evaluate, instance);
return (Func<T, object>)lambda.Compile();
}
private static Expression<Func<U, bool>> FuncToExpression<U>(Func<U, bool> predicate)
{
return argument => predicate(argument);
}
public class TestPredicate
{
public int Number { get; set; }
}
}
如果您說出當前出了問題,那將會有所幫助,但是我認為您只需要擺脫第一個Lambda
調用即可。 我也對變量名做了一些更改:
Expression<Func<U, bool>> test = FuncToExpression(predicate);
var parameter = Expression.Parameter(propertyInfo.DeclaringType, "instance");
var property = Expression.Property(parameter, propertyInfo);
var trueOption = Expression.TypeAs(property, typeof(object));
var falseOption = Expression.Constant(alternative);
var conditional = Expression.Condition(test, trueOption, falseOption);
var lambda = Expression.Lambda<Func<T, object>>(conditional, parameter);
return lambda.Compile();
如果這不起作用,請以什么方式告訴我們-理想情況下,請在您的問題中編輯一個簡短但完整的示例程序。
此擴展方法將允許您提供選擇器(獲取屬性),驗證器(驗證屬性)和默認值:
public static P GetValueOrDefault<T, P>(this T item, Func<T, P> selector, Func<P, bool> validator, P defaultValue)
{
if (item == null)
return defaultValue;
P value = selector(item);
if (validator == null || !validator(value))
return defaultValue;
return value;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.