2010-02-26 5 views
16

У меня есть код, который генерирует различные делегаты Func<>, используя System.Linq.Expressions и Expression.Lambda<Func<>>.Compile() и т. Д. Я хотел бы иметь возможность сериализовать сгенерированные функции в сборку для последующего использования. Раньше я делал некоторые вещи с помощью System.Reflection.Emit, но теперь, когда Linq Expressions я бы больше не пошел по этому маршруту.Как я могу испустить выражение System.Linq.Expression?

Есть ли механизм для сериализации скомпилированного выражения или какого-либо моста из пространства имен Expressions в пространство имен Emit?

Редактировать

Некоторые фон для связи: Я работаю над двигателем запроса (в основном для собственного назидания и удовольствия). Учитывая оператор SQL, я хотел бы проанализировать и преобразовать его в лямбда-функцию, а затем сериализовать его на диск для последующего (и повторного выполнения).

В псевдокоде я к этой точке:

Func<IEnumerable<T>, IEnumerable<T1>> query = Query.Parse<T, T1>("Select field AS A, field1 AS B from T where T.field2 > 5"); 

(где поле, поле1 и поле2 являются свойствами типа Т и и B являются свойствами от Тип T1. , и я могу передать любое перечисление <T> по адресу query и вернитесь и перечисление <T1>, которое соответствует критериям запроса.

Поэтому я хотел бы сериализовать query на диск как уже скомпилированную сборку, поэтому на более позднюю дату я могу загрузить его и оценить разные наборы <T> без разбора и компиляции. Я изображая что-то вдоль линий:

AssemblyBuilder builder = new AssemblyBuilder(...); 
ModuleBuilder module = builder.DefineDynamicModule(...); 
TypeBuilder type = module.DefineType(...); 
type.AddMethod(query); // <--- where this piece does not exist as far as I know 
builder.Emit(...) 

ответ

3

я не уверен, что именно ваша большая картина, но смотрит исключительно на свой второй пункт, вы можете писать чистый код на основе Expression, построить его, а затем откройте сборку в рефлекторе с использованием надстройки языка «Reflection.Emit». Этот фрагмент мета-мета-трюков покажет вам заявления Reflection.Emit, необходимые для генерации вашего кода Expression/Lambda динамически.

-Oisin

+0

Я думаю, что вижу, что вы получаете, но если вы посмотрите на мое редактирование: я не знаю, как будут выглядеть выражения, пока не будет оценена входная информация. – dkackman

3

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

Похоже, что вы можете обойти это, позвонив по номеру expr.Compile().Method.GetMethodBody().GetILAsByteArray(), чтобы получить IL как байты, которые затем могут быть записаны в MethodBuilder в сборке, которую вы могли бы записать в файл. К сожалению, это не сработает - вызов GetMethodBody() завершился неудачно, потому что делегат является динамическим.

3

LambdaExpression имеет метод CompileToMethod, который нацелен на MethodBuilder. Используя это и Reflection.Emit, вы должны иметь возможность создать класс и записать его в сборку.