2017-01-07 5 views
12

Я теперь портировании некоторых библиотек, которая использует выражения .Net Core приложения и столкнулся с проблемой, что вся моя логика основана на LambdaExpression.CompileToMethod, которая просто отсутствует в Вот примере код:Альтернативы CompileToMethod в .Net Standard

public static MethodInfo CompileToInstanceMethod(this LambdaExpression expression, TypeBuilder tb, string methodName, MethodAttributes attributes) 
{ 
    ... 

    var method = tb.DefineMethod($"<{proxy.Name}>__StaticProxy", MethodAttributes.Private | MethodAttributes.Static, proxy.ReturnType, paramTypes); 
    expression.CompileToMethod(method); 

    ... 
} 

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

Я пытался использовать var method = expression.Compile().GetMethodInfo();, но в этом случае я получаю сообщение об ошибке:

System.InvalidOperationException : Unable to import a global method or field from a different module.

Я знаю, что я могу излучать IL вручную, но мне нужно точно конвертировать Expression -> к MethodInfo привязана к какому конкретному TypeBuilder вместо построив себя DynamicMethod на нем.

+1

Wow, пытаясь ответить на этот вопрос, я только выяснил, что .Net-core не имеет документации и не может легко найти, что было заменено тем, что ... Удачи в этом порту ... –

+0

@LucasCorsaletti Я думаю, что очень сложно предоставить такую ​​документацию, потому что я думаю, что даже основная команда .net не знает, что было заменено тем, что :) В любом случае, спасибо за попытку –

+0

Интересно, я смотрю этот вопрос. Просто попытался создать методы класса/экземпляра с помощью Linq.Expressions и старого .NET 4.5. Динамические методы могут быть созданы как методы экземпляра в отношении атрибутов видимости, но требуются Reflection.Emit. Построение его с помощью Linq.Expressions было гораздо более читаемым, но его нельзя было использовать в качестве метода экземпляра.Тем не менее, я мог бесстыдно обращаться к внутренним и частным лицам, делая такую ​​же функциональность возможной, как и с помощью метода экземпляра. Я просто начинающий с генерации кода времени выполнения ... –

ответ

5

Это не идеальное решение, но это стоит обратить внимание, если вы не хотите, чтобы написать все с нуля:

  1. Если вы посмотрите на CompileToMethod реализации, вы увидите, что под капотом он использует внутренний LambdaCompiler класс.
  2. Если вы копаете еще глубже, вы увидите, что LambdaCompiler использует System.Reflection.Emit для преобразования lambdas в MethodInfo.
  3. System.Reflection.Emit поддерживается .NET Core.
  4. Учитывая это, мое предложение состоит в том, чтобы попытаться повторно использовать исходный код LambdaCompiler. Вы можете найти его here.

Самая большая проблема с этим решением является то, что:

  1. LambdaCompiler распространен среди многих файлов, так что это может быть громоздким, чтобы найти то, что нужно для его компиляции.
  2. LambdaCompiler может использовать некоторый API, который вообще не поддерживается .NET Core.

Несколько дополнительных комментариев:

  1. Если вы хотите проверить, какие API поддерживается, которые используют платформу .NET API Catalog.
  2. Если вы хотите увидеть различия между стандартными версиями .NET, используйте сайт this.
+0

Я декомпилировал 'CompileToMethod' перед тем, как задать вопрос, однако я остановился, когда узнал, что' LambdaCompiler' является внутренним. Однако теперь у меня появилась идея, что мы можем вызвать некоторые внутренние методы посредством отражения. * Нет, велоцираптор, не ешь меня ([у тебя есть шутка] (https://xkcd.com/292/)). * Я делаю некоторые исследования и возвращаюсь с результатами и отмечаю этот ответ, если нет другой хочет помочь нам. –

+0

Так что я здесь. По неизвестной причине «.Net Standard» отсутствует конструктор 'LambdaCompiler (AnalyzedTree tree, LambdaExpression lambda, MethodBuilder method)'. Нет причин для его не предоставления, потому что 'MethodBuilder' используется в другой перегрузке, поэтому на каждую требуемую сборку ссылаются. Думаю, я должен опубликовать вопрос о каком-то репозитории (corefx?). В настоящее время я хотел бы создать запрос на перенос, фиксирующий эту проблему, но не уверен в репо. –

+0

После просмотра источников «corefx» я обнаружил, что это сделано намеренно с флагом 'FEATURE_COMPILE_TO_METHODBUILDER'. Однако не знаю, почему. –