Как вручную построить дерево выражений, когда у меня есть только общие типы и значения экземпляров? - PullRequest
2 голосов
/ 03 декабря 2011

У меня есть общий класс, как показано ниже:

public class MyClass<T, TProperty>
{
     MyClass(Expression<Func<T, TProperty>> expression)
     {
     }
}

В моем случае я хочу динамически создать экземпляр этого класса с помощью Activator. Итак, мне нужно создать выражение для конструктора. У меня есть типы (System.Type) и объект (System.Object), и я хочу что-то вроде ниже:

Expression<Func<T, TProperty>> exp = x => someValue;

"someValue" объявлено как объект, но его реальный тип определенно является TProperty. Это разрешается отражением, поэтому тип здесь - объект.

Проблема в том, что типы T и TProperty будут общими, я не знаю типы до времени выполнения, поэтому я не могу привести "someValue" к TProperty. То, что мы имеем, это typeof (T), typeof (TProperty) и объект -, -

1 Ответ

4 голосов
/ 03 декабря 2011

Хорошо, я думаю, что понимаю вопрос.

Приведенный пример ввода:

Type typeOfT = typeof(int);
Type typeOfTProperty = typeof(string);
object someValue = "Test";

Вы хотите создать код, эквивалентный:

var myClassInstance = new MyClass<int, string>(t => "Test");

Вот какВы можете сделать это.

Сначала создайте дерево выражений:

var parameter = Expression.Parameter(typeOfT, "t");
var body = Expression.Constant(someValue, typeOfTProperty);

// Will automatically be an Expression<Func<T, TProperty>> without any extra effort.
var lambda = Expression.Lambda(body, parameter);

И затем используйте отражение для создания экземпляра MyClass<T, TProperty>:

var myClassType = typeof(MyClass<,>).MakeGenericType(typeOfT, typeOfTProperty);

//  Make the MyClass<,> constructor public first...
var myClassInstance = Activator.CreateInstance(myClassType, lambda);
...