我有一个linq表达式,用于将属性传递给需要它的方法。但是我不能知道属性的类型,直到运行时。我需要能够找出由表达式表示的参数的原始类型,但它总是显示在System.Object
。
我有下面的例子类:
public class SomeClass
{
public int SomeProp { get; set; }
}
我有以下表达式,其中第二个泛型类型是System.Object
:
Expression<Func<SomeClass, object>> expression = x => x.SomeProp;
我需要能够通过以下测试:
public void PropertyShouldBeInt()
{
Expression<Func<SomeClass, object>> expression = x => x.SomeProp;
Assert.AreEqual(expression.Body.Type, typeof(int));
}
我意识到问题的根源在于我的表达式指定object
作为属性类型。但是我传入了一个int
属性。对我来说,我应该能够找出传递给表达式的属性的实际类型似乎是合理的。以以下测试为例:
public void AnObjectShouldKnowThatItIsAlsoSomethingElse()
{
object someObject = new SomeClass();
Assert.IsInstanceOfType(someObject, typeof (SomeClass));
}
我觉得我应该能够引用SomeClass
类型并比较属性以找到原始类型。如能提供建议,我将不胜感激。或者,如果你有更好的方法,我洗耳恭听。
EDIT(找到解决方案后):
在下面的优秀答案之后,我想我应该发布我的测试的工作版本,以防其他人有同样的问题:
public void PropertyShouldBeInt()
{
Expression<Func<SomeClass, object>> expression = x => x.SomeProp;
Assert.AreEqual(((UnaryExpression) expression.Body).Operand.Type, typeof (int));
}
Expression<Func<SomeClass, object>> expression = x => x.SomeProp;
PropertyShouldBe<int>(expression);
// ...
public void PropertyShouldBe<T>(Expression<Func<SomeClass, object>> expr)
{
// error-checking etc removed for brevity
MemberExpression me;
switch (expr.Body.NodeType)
{
case ExpressionType.Convert:
case ExpressionType.ConvertChecked:
var ue = expr.Body as UnaryExpression;
me = ((ue != null) ? ue.Operand : null) as MemberExpression;
break;
default:
me = expr.Body as MemberExpression;
break;
}
Assert.AreEqual(me.Type, typeof(T));
}
显示为object
,因为你说它应该是object
,当你这样做
Expression<Func<SomeClass, object>>
如果你想让它是int
,它应该是
Expression<Func<SomeClass, int>>
我想要理解的是,你正在传递一些明确声明自己是object
类型的typeof
的东西,然后问为什么它不给你int
。也许这样就够了?
Assert.AreEqual(expression().GetType(), typeof(int))