CodeDOM を使用して、ユーザー定義の式を評価し、クラスのアセンブリを作成し、アセンブリを読み込むクラスを作成するプロジェクトに取り組んでいます。かなりの数のユーザー定義式が存在する可能性があるため、最初に AppDomain を作成し、その AppDomain 内のアセンブリに対して CodeDOM の作成/読み込みと実行を実行してから、AppDomain をアンロードします。
かなり検索したところ、既存のアセンブリを AppDomain に読み込む方法の例がたくさん見つかりましたが、AppDomain内からアセンブリを作成する方法を示す例が見つからないようです。
この例 ( DynamicCode ) は CodeDOM を使用してアセンブリを作成し、それを AppDomain に読み込みますが、作成者はアセンブリをディスクに生成しています。生成されたアセンブリのクリーンアップを管理する必要がないように、アセンブリをメモリ内に生成することをお勧めします。(ただし、一時フォルダーに .dll が作成されます)。
誰かがこれを行う方法の例を教えてもらえますか?
どんな助けでも大歓迎です。
私のコードからの抜粋をいくつか含めました。
private string CreateSource()
{
CodeCompileUnit codeUnit = new CodeCompileUnit();
CodeNamespace codeNamespace = new CodeNamespace(Namespace);
CodeTypeDeclaration codeClass = new CodeTypeDeclaration
{
Name = "ExpressionEvaluator",
IsClass = true,
TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed
};
codeNamespace.Types.Add(codeClass);
codeUnit.Namespaces.Add(codeNamespace);
AddMethods(codeClass);
string result = GenerateSourceCode(codeUnit);
return result.ToString();
}
private CompilerResults CompileSource(string source)
{
using (CodeDomProvider provider = new CSharpCodeProvider())
{
CompilerParameters parameters = CreateCompilerParameters();
CompilerResults result = CompileCode(provider, parameters, source);
return result;
}
}
private static CompilerParameters CreateCompilerParameters()
{
CompilerParameters result = new CompilerParameters
{
CompilerOptions = "/target:library",
GenerateExecutable = false,
GenerateInMemory = true
};
result.ReferencedAssemblies.Add("System.dll");
return result;
}
private object RunEvaluator(CompilerResults compilerResults)
{
object result = null;
Assembly assembly = compilerResults.CompiledAssembly;
if (assembly != null)
{
string className = "ExpressionEvaluator";
object instance = assembly.CreateInstance("Lab.ExpressionEvaluator");
Module[] modules = assembly.GetModules(false);
Type type = (from t in modules[0].GetTypes()
where t.Name == className
select t).FirstOrDefault();
MethodInfo method = (from m in type.GetMethods()
where m.Name == "Evaluate"
select m).FirstOrDefault();
result = method.Invoke(instance, null);
}
else
{
throw new Exception("Unable to load Evaluator assembly");
}
return result;
}
これらのコード スニペットは、私のプロジェクトの基本的な機能を示していると思います。あとは、それを独自の AppDomain にラップするだけです。