我有一个基类(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();
但是抛出了无效的强制转换异常。我应该能够在表达式中进行投射吗?
由于
答案 0 :(得分:3)
UkBankAccount
是BankAccount
但是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.SomeProperty
,x.Status
,x.Name
和x.SortCode
必须< / strong>是x.AccountNumber
(或其中一个基类,如果存在)的一部分。