Как использовать динамически определяемый тип в качестве параметра для Lambda<Func> ?

#dynamic #lambda #c#-3.0

#динамический #лямбда #c #-3.0

Вопрос:

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

Нет, вы не можете.

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

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

или

 object list = new List<t>(); 
  

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

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

Что вы МОГЛИ бы сделать, это всегда возвращать Func<object, bool> и приводить объект к желаемому типу В лямбда-функции (поэтому используйте a 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);
  

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

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

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

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