如何将PropertyInfo
转换为可用于调用StructuralTypeConfiguration<TStructuralType>.Ignore<TProperty>(Expression<Func<TStructuralType, TProperty>> propertyExpression)
方法的属性表达式?
我尝试使用Expression.Property()
来构造表达式,但是当我将此表达式用作propertyExpression
参数时,我收到以下错误:
The type arguments for method cannot be inferred from the usage. Try specifying the type arguments explicitly.
此错误可能是指TProperty
类型参数,我不知道如何指定只有PropertyInfo
。
更新
无效的代码:
var propertyInfo = typeof(Foo).GetProperties()[0];
var expression = Expression.Default(typeof(Foo));
var expressionProperty = Expression.Property(expression, propertyInfo);
Ignore(expressionProperty);
答案 0 :(得分:21)
var entityType = propertyInfo.DeclaringType;
var parameter = Expression.Parameter(entityType, "entity");
var property = Expression.Property(parameter, propertyInfo);
var funcType = typeof(Func<,>).MakeGenericType(entityType, propertyInfo.PropertyType);
var lambda = Expression.Lambda(funcType, property, parameter);
structureConfiguration.GetType()
.GetMethod("Ignore")
.MakeGenericMethod(propertyInfo.PropertyType)
.Invoke(structureConfiguration, new[]{lambda});
答案 1 :(得分:2)
属性表达式要求属性访问权限在特定对象上。您可以在这里选择一些选项。首先,如果在一个实体对象中完成,您可以简单地使用ConstantExpression来构建属性表达式:
// Already have PropertyInfo in propInfo
Expression.Property(Expression.Constant(this, this.GetType()), propInfo)
但是,由于您需要Expression<Func<TStructuralType, TProperty>>
,因此您似乎必须使用ParameterExpression构建它:
ParameterExpression pe = Parameter.Expression(typeof(MyEntity), "eParam");
Expression propExp = Expression.Property(pe, propInfo);
然而,这是踢球者......这只是一个会员表达。要转换为您需要的表达式,您需要使用Expression.Lambda
来获取Func&lt;&gt;表达你需要的类型。问题?您不知道用于定义lambda表达式的泛型参数的属性类型!
Expression<Func<MyEntity, ????>> eFunc = Expression.Lambda<Func<MyEntity, ????>>(propExp, pe);
这就是这样做的问题的症结所在。这并不是说它无法完成......只是在这种方式下使用这种方法是行不通的。您将不得不使用一点运行时和静态类型技巧(以及明智地使用Actions而不是Funcs)来使其正常工作。
答案 2 :(得分:1)
TProperty
仅存在于c#源代码文本中。编译器始终将其解析为具体类型。如果你有方法
void Test<T>(T arg)
{
}
并像这样称呼它
Test("hello");
Test(3);
编译器为两种方法生成代码!
void Test(string arg)
{
}
void Test(int arg)
{
}
这意味着如果您想要一个可调用的方法,则必须为泛型参数提供具体类型。