2011-05-03 360 views
7

我想“包装”属于特定类型的特定属性的getter函数。 我有一个抽象类,等被定义如下:Lambda表达式:将参数强制转换为基类型

public abstract class MyAbstractClass<T> where T : MyType 
{ 
    // ... 
} 

好吧,假设我有一个具体的类像下面的一个:

public abstract class MyConcreteClass : MyAbstractClass<MyConcreteType> 
{ 
    // ... 
} 

而现在,辅助方法应该返回一个包装为getter方法:

private Func<MyAbstractClass<T>, Object> GetPropertyGetter(PropertyInfo property) 
{ 
    var instanceType = Expression.Parameter(property.DeclaringType, "i"); 

    // Taking getter's "body". 
    var getterBody = Expression.Property(instanceType, property); 

    // Cast to a generic Object. 
    var body = Expression.TypeAs(getterBody, typeof(Object)); 

    // Build the expression. 
    var exp = Expression.Lambda<Func<MyAbstractClass<T>, Object>>(body, instanceType); 
    return exp.Compile(); 
} 

就像预期的,我得到以下异常:

类型'MyConcreteClass'的参数表达式不能用于 类型为'MyAbstractClass <MyConcreteType>'的委托参数。

有没有办法“强制”这种铸造?提前致谢。

+1

这个问题非常混乱。为什么有一个叫做“MyConcreteClass”的抽象类。 “具体”与“抽象”是相反的;这是故意混淆的吗?两个“T”是相同的,还是两个不同的类中有两个不同的T的声明?为什么你首先想要做这件奇怪的事情? – 2011-05-03 07:08:12

回答

11

如果我正确理解你的问题,你想创建这样一个lambda表达式:

Func<MyAbstractClass<T>, Object> f = i => ((MyConcreteClass)i).SomeProperty; 

除了要提供财产SomeProperty作为参数。那么,如果你想以编程方式构建该表达式,则必须完全相同:具有表达式参数i(类型MyAbstractClass<T>),将其转换为MyConcreteClass,然后访问属性SomeProperty

public Func<MyAbstractClass<T>, Object> GetPropertyGetter(PropertyInfo property) 
{ 
    var parameter = Expression.Parameter(typeof(MyAbstractClass<T>), "i"); 

    var cast = Expression.TypeAs(parameter, property.DeclaringType); 

    var getterBody = Expression.Property(cast, property); 

    var exp = Expression.Lambda<Func<MyAbstractClass<T>, Object>>(
     getterBody, parameter); 

    return exp.Compile(); 
} 

说了这么多,我也绝对不知道你为什么会想这样做,所以你最好是真的相信这是你想要做什么,有没有做你的什么更好的方法实际上想要做的。

+0

+1我正在寻找'Expression.TypeAs'的样本。感谢分享。 – digaomatias 2013-12-30 14:47:52

0

不应该从通用类型构建实例类型吗?

var genericType = typeof(MyAbstractClass<>).MakeGenericType(property.DeclaringType); 
var instanceType = Expression.Parameter(genericType , "i"); 
相关问题