Как я могу найти тип свойства в выражении, когда универсальный тип является объектом? - PullRequest
1 голос
/ 01 августа 2011

У меня есть выражение linq, предназначенное для передачи свойства методам, которым оно необходимо. Но я не могу знать тип свойства до времени выполнения. Мне нужно найти исходный тип параметра, который представлен выражением, но он всегда отображается в System.Object.

У меня есть следующий пример класса:

public class SomeClass
{
    public int SomeProp { get; set; }
}

У меня есть следующее выражение, где 2-й универсальный тип: 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 и сравнивать свойства, чтобы найти исходный тип.Ваши предложения о том, как это сделать, будут оценены.ИЛИ, если у вас есть лучший способ сделать это, у меня все уши.

РЕДАКТИРОВАТЬ (после того, как решение найдено):

После превосходного ответа ниже,Я решил опубликовать рабочую версию своего теста на случай, если у других возникнет такая же проблема:

public void PropertyShouldBeInt()
{
    Expression<Func<SomeClass, object>> expression = x => x.SomeProp;
    Assert.AreEqual(((UnaryExpression) expression.Body).Operand.Type, typeof (int));
}

Ответы [ 2 ]

3 голосов
/ 01 августа 2011
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));
}
0 голосов
/ 01 августа 2011

Это отображается как object, потому что вы говорите, что должно быть object, когда вы делаете

Expression<Func<SomeClass, object>>

Если вы хотите, чтобы оно было int, оно должно быть

Expression<Func<SomeClass, int>>

Я пытаюсь донести до вас, что вы передаете нечто, явно заявляющее о себе, типа object, к typeof, а затем спрашиваете, почему это не дает вам int.Может быть, этого будет достаточно?

Assert.AreEqual(expression().GetType(), typeof(int))
...