#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