How can I find the type of a property in an expression when the generic type is object?
I have an linq expression that is meant to pass a property around to methods that need it. But I cannot know the type of the property until runtime. I need to be able to find out the original type of the parameter that is represented by the expression, but it always shows up at System.Object
.
I have the following example cla开发者_StackOverflow社区ss:
public class SomeClass
{
public int SomeProp { get; set; }
}
I have the following expression where the 2nd generic type is System.Object
:
Expression<Func<SomeClass, object>> expression = x => x.SomeProp;
I need to be able to pass the following test:
public void PropertyShouldBeInt()
{
Expression<Func<SomeClass, object>> expression = x => x.SomeProp;
Assert.AreEqual(expression.Body.Type, typeof(int));
}
I realize the problem is rooted in that my expression specifies object
as the property type. But I'm passing in an int
property. It seems reasonable to me that I should be able to find out the actual type of the property that has been passed to the expression. Take the following test for example:
public void AnObjectShouldKnowThatItIsAlsoSomethingElse()
{
object someObject = new SomeClass();
Assert.IsInstanceOfType(someObject, typeof (SomeClass));
}
I feel like I should be able to reference the SomeClass
type and compare the properties to find the original type. Your suggestions as to how to do that would be appreciated. OR, if you have a better way to do this, I'm all ears.
EDIT (after solution was found):
After the excellent answer below, I thought I'd post the working version of my test in case others have the same issue:
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));
}
It shows up as object
because you say it should be object
when you do
Expression<Func<SomeClass, object>>
If you want it to be int
, it should be
Expression<Func<SomeClass, int>>
What I am trying to get across is that you are passing something that explicitly states itself to be of type object
to typeof
, then asking why it isn't giving you int
. Maybe this would suffice?
Assert.AreEqual(expression().GetType(), typeof(int))
精彩评论