2015-06-15 3 views
4

Я пытаюсь сделать некоторые выражения, где я буду использовать лямбду, чтобы создать два метода: селектор и условие. Упрощенное использование - condition(selector(data)), но тип intemediate известен только во время выполнения. У меня есть следующий код, который работает до тех пор, пока объект intemediate является объектом, но во время выполнения я знаю реальный тип и хотел бы использовать его.Выражение Лямбда с типами, известными во время выполнения

public static ICondition<TData> GetRelayConditionByReflection(string name, string message, string assemblyName, 
     string fullyQualifiedName, string conditionMethodName, string selectorMethodName) { 
     var asm = Assembly.LoadFrom(assemblyName); 
     var type = asm.GetType(fullyQualifiedName); 
     var selectorMi = type.GetMethod(selectorMethodName, BindingFlags.Static | BindingFlags.Public); 
     var conditionMi = type.GetMethod(conditionMethodName, BindingFlags.Static | BindingFlags.Public); 

     var tCondType = selectorMi.ReturnType; 
     var returnType = typeof(RelayCondition<,>); 
     var typeArgs = new[] { typeof(TData), tCondType }; 



     var paramTData = Expression.Parameter(typeof(TData), "data"); 
     var selector = Expression.Lambda<Func<TData, object>>(
      Expression.Call(selectorMi, paramTData), paramTData).Compile(); 

     var paramTCondition = Expression.Parameter(tCondType, "condition"); 

     var condition = Expression.Lambda<Func<object, bool>>(
      Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile(); 



     return (ICondition<TData>)Activator.CreateInstance(returnType.MakeGenericType(typeArgs), name, condition, message, selector); 
    } 

В частности, существует Expression.Lambda<Func<TData, object>> и Expression.Lambda<Func<object, bool>>, где object в настоящее время только позволяет тип intemediate быть объектом.

Возможно ли создать это с типом, известным только во время выполнения? Я открыт для других подходов для всей проблемы, пока производительность не является attrocius.

+0

Почему вам небезразличен промежуточный тип? – Servy

+0

Я не, но если я использую объект, я оба метода должен использовать объект в своем определении, и я хотел бы избежать этого. – hvidgaard

ответ

2

Если вам не требуется скрытое понижение (например, объявление Func<object>, когда по правде вы вернете метод Func<Foo>), вы можете использовать не общий метод Expression.Lambda(). Она возвращает LambdaExpression, но на самом деле она возвращает Expression<> из Func<> или Action downcasted к LambdaExpression (Expression<> подкласс LambdaExpression), так:

var condition = Expression.Lambda(
     Expression.Call(conditionMi, paramTCondition), paramTCondition).Compile(); 

Теперь condition является Delegate, но на самом деле это Func<> (или Action, если у него был тип возврата void).

+0

Это работает, и во время выполнения он выясняет, что делегат имеет подходящий тип и генерирует исключение, если нет. Типы сохраняются и все еще не работают быстро в случае ошибки. Спасибо. – hvidgaard

Смежные вопросы