将派生类转换为表达式中的父类

时间:2017-03-22 12:22:34

标签: c#

我有一个基类(BankAccount),它的派生类型为UkBankAccount。

我得到子类的字段列表作为表达式:

var properties = new Expression<Func<UkBankAccount, object>>[] {
    x => x.Status,
    x => x.Name,
    x => x.SortCode,
    x => x.AccountNumber
};

但是后来想把它转换为BankAccount类型,这样我就可以使用它了。我试过了:

updatedProperties = properties.ToList()
   .Cast<Expression<Func<BankAccount, object>>>()
   .ToArray();

但是抛出了无效的强制转换异常。我应该能够在表达式中进行投射吗?

由于

2 个答案:

答案 0 :(得分:3)

UkBankAccountBankAccount

但是Func<UkBankAccount, object>无法分配给Func<BankAccount, object>,事实上它是另一种方式:Func<BankAccount, object>可分配给Func<UkBankAccount, object>。想一想:当你有一个能够获得各种账户的功能时,肯定可以使用英国账户。但另一种方式并非如此。

但这并不意味着Expression<Func<BankAccount, object>>应该可以分配给Expression<Func<UkBankAccount, object>>。它不是。通用逆变法不适用于班级。

即便如此,你似乎想要的却是另一种方式。

  

我是否可以在表达式中进行投射?

不,类型系统不允许将Expression<Func<UkBankAccount, object>>转换,转换或以其他方式分配给Expression<Func<BankAccount, object>>

你需要做的是产生相当于

的东西
var properties = new Expression<Func<BankAccount, object>>[] {
    x => ((UkBankAccount)x).Status,
    x => ((UkBankAccount)x).Name,
    x => ((UkBankAccount)x).SortCode,
    x => ((UkBankAccount)x).AccountNumber
};

如果BankAccount上也存在属性,则可以跳过强制转换。

请注意,这些演员表可能会失败,这就是Func<UkBankAccount, object>无法分配给Func<BankAccount, object>的原因。

答案 1 :(得分:0)

你必须重写表达式...使用我在另一个问题中发布的SimpleParameterReplacer

var updatedProperties = Array.ConvertAll(properties, exp =>
{
    var parameter = Expression.Parameter(typeof(BankAccount), exp.Parameters[0].Name);
    var body = new SimpleParameterReplacer(exp.Parameters[0], parameter).Visit(exp.Body);
    var exp2 =  Expression.Lambda<Func<BankAccount, object>>(body, parameter);
    return exp2;
});

使用SimpleParameterReplacer()重写表达式的“正文”(将UkBankAccount类型参数的使用实例替换为BankAccount类型的参数)然后重建lambda表达式(用于更改委托类型)。

重要提示:如果SomeProperty的{​​{1}}属于基类,则此代码有效>而不是派生类 ...在您的示例中,x => x.SomePropertyx.Statusx.Namex.SortCode 必须< / strong>是x.AccountNumber(或其中一个基类,如果存在)的一部分。