Как использовать динамически определенный тип в качестве параметра лямбда>? - PullRequest
0 голосов
/ 26 октября 2011

Я динамически создаю лямбда-выражение (на основе пользовательского ввода, но в данный момент использую фиктивные значения для проверки концепции) для типа, который я буду знать только во время выполнения. Поэтому мне нужно передать T часть Func<T,TResult> как динамический тип, поскольку я не буду знать тип до времени выполнения (TResult всегда будет bool).

Кажется, я не могу передать переменную Type или использовать typeof с обобщениями. В основном я пытаюсь сделать что-то вроде этого:

// (f => f.Baz == 1)
Type theType = Type.GetType("Foo");
ParameterExpression pe = Expression.Parameter(theType, "f");
Expression left = Expression.Property(pe, theType.GetProperty("Baz"));
Expression right = Expression.Constant(1);
Expression expr = Expression.Equal(left, right);
// This works fine but uses a hard-coded type, which I won't know until runtime:
// var lambda = Expression.Lambda<Func<Foo,bool>>(expr, new ParameterExpression[] { pe }).Compile();
var lambda = Expression.Lambda<Func<theType, bool>>(expr, new ParameterExpression[] { pe }).Compile();

Однако я не могу использовать переменную theType в качестве части T функции. Как я могу это исправить?

1 Ответ

1 голос
/ 26 октября 2011

Нет, ты не можешь.

Например, в C # вы не можете:

Type t = typeof(int);
List<t> list = new List<t>(); 

или

object list = new List<t>(); 

Если вы не используете отражение, но затем вы должны поместить список в object, и вы можете использовать его только через отражение.

Итак, если вы хотите, вы можете сохранить Func<> в object (или dynamic), но не более.

То, что вы МОЖЕТЕ сделать, это всегда возвращать Func<object, bool> и приводить объект к требуемому типу В функции лямбда (так что используйте Expression.Convert(pe, theType));

Или вы можете использовать динамический:

// lambda == Func<Foo, bool>
dynamic lamdba = Expression.Lambda(expr, new ParameterExpression[] { pe }).Compile();

bool res = lambda(myvalue);

или

// lambda == Func<Foo, bool>
Delegate lamdba = Expression.Lambda(expr, new ParameterExpression[] { pe }).Compile();
bool res = (bool)lambda2.DynamicInvoke(t);

Для некоторых «не настоящих» тестов (в StopWatch.Ticks смотрите их только для пропорций) (Режим выпуска + Запуск без отладки + некоторые бесполезные циклы, чтобы они были «горячими»):

  236384685 dynamic
   56773593 Func<object, bool> + cast
10556024247 DynamicInvoke

как примечание, Func<Foo, bool> имеет такую ​​же скорость, поэтому при дополнительном использовании скорость не теряется.

Вы можете увидеть код здесь http://ideone.com/qhnVP3

...