【问题标题】:Lambda Expression: cast parameter to base typeLambda 表达式:将参数转换为基本类型
【发布时间】:2011-05-03 06:58:07
【问题描述】:

我想为属于特定类型的特定属性“包装”getter 函数。 我有一个抽象类,定义如下:

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' 类型的委托参数。

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

【问题讨论】:

  • 这个问题非常令人困惑。为什么会有一个名为“MyConcreteClass”的抽象类。 “具体”和“抽象”是对立的;这是故意混淆视听吗?两个“T”是相同的,还是在两个不同的类中有两个不同的 T 声明?你为什么要首先尝试做这种奇怪的事情?

标签: c# lambda generics


【解决方案1】:

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

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

除非您想提供哪个属性是SomeProperty 作为参数。好吧,如果您想以编程方式构建该表达式,您必须完全相同:拥有表达式参数i(类型为MyAbstractClass&lt;T&gt;),将其转换为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();
}

话虽如此,我完全不知道你为什么要这样做,所以你最好确定这就是你想做的事情,并且没有更好的方法来做你真正想做的事情.

【讨论】:

  • +1 我正在寻找Expression.TypeAs 的样本。感谢分享。
【解决方案2】:

您不应该从泛型类型构建实例类型吗?

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    相关资源
    最近更新 更多