Компилировать и использовать класс во время выполнения - PullRequest
2 голосов
/ 20 августа 2011

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

Как взять строку динамически сгенерированного исходного кода и скомпилировать ее во время выполнения?

Как я могу выполнить этот код?

Я предполагаю, что у меня будет статический список правил, который будет обновляться по мере добавления правил. Что-то вроде:

static Dictionary<string, Rule> Rules { get; set; }
static void RefreshRules ()
{
    var newRules = DataLayer.GetRules().Where(r => !this.Rules.ContainsKey(r.Name));
    foreach (var rule in newRules)
    {
        this.Rules[rule.Name] = CompileRule(rule.Code);
    }
}

Или я бы перекомпилировал сборку и затем перезагрузил ее в уже работающее приложение?

Ответы [ 2 ]

5 голосов
/ 20 августа 2011

Я бы порекомендовал использовать Деревья выражений вместо динамической компиляции кода.

Когда вы компилируете какой-либо источник, полученная сборка склеивается в ваше основное приложение и не может быть отсоединенабольше.Это приводит к растущему использованию памяти и потенциально опасному поведению.Деревья выражений созданы только для таких целей, как ваша.

3 голосов
/ 20 августа 2011

Несколько грубых примеров (компиляция исходного кода, создание экземпляра, вызов метода с параметрами с использованием Reflection):

CodeDomProvider P = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("C#");
CompilerParameters O = new CompilerParameters();
O.GenerateInMemory = true;
O.ReferencedAssemblies.Add(@"System.dll");
//O.ReferencedAssemblies.Add(@"System.Net.dll");

O.IncludeDebugInformation = false;

CompilerResults R = P.CompileAssemblyFromSource(O, new string[] { "using System; using System.Reflection; namespace ABC.TestXXX {     // your source code goes here }" });

Assembly _B_ = R.CompiledAssembly;
// create an instance
object YY = _B_.CreateInstance("ABC.TestXXX.MyClass");
// call method returning bool and taking one string and one object
YR = (bool)_B_.GetType("ABC.TestXXX.MyClass").GetMethod("TestB").Invoke(YY, new object[] { "Hallo", SomeObject });

Некоторые ссылки с деталями:

Для вашего случая вы можете создать правила Action <> / Delegates, которые в свою очередь вызывают скомпилированные методы.и поместите их в словарь <> ... чтобы они стали читабельными при их вызове и т. д.

...