开发者

How can I find the type of a property in an expression when the generic type is object?

开发者 https://www.devze.com 2023-03-23 23:30 出处:网络
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

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))
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号