実行時にリフレクションによって生成されるクラスの IL コードを抽出して、ディスクに保存するにはどうすればよいですか? できれば。これらのクラスを生成するコードを制御することはできません。
最終的に、この IL コードをディスクから別のアセンブリにロードしたいと考えています。
クラスをシリアライズ/デシリアライズできることはわかっていますが、純粋に IL コードを使用したいと考えています。私はセキュリティへの影響については気にしていません。
Mono 2.10.1 の実行
実行時にリフレクションによって生成されるクラスの IL コードを抽出して、ディスクに保存するにはどうすればよいですか? できれば。これらのクラスを生成するコードを制御することはできません。
最終的に、この IL コードをディスクから別のアセンブリにロードしたいと考えています。
クラスをシリアライズ/デシリアライズできることはわかっていますが、純粋に IL コードを使用したいと考えています。私はセキュリティへの影響については気にしていません。
Mono 2.10.1 の実行
またはさらに良いことに、Mono.Cecil を使用します。
個々の命令を取得し、それらを操作して逆アセンブルすることもできます ( mono decompiler の追加を使用)。
逆コンパイラは進行中の作業であることに注意してください (前回チェックしたときは、ラムダ式と Visual Basic 例外ブロックを完全にはサポートしていませんでした)、これらの境界条件に達しない限り、C# で非常に簡単にかなり逆コンパイルされた出力を得ることができます。 . また、そこから作業が進みました。
一般に、Mono Cecil では、IL を新しいアセンブリに書き込むこともできます。その後、ブリーディング エッジで遊んでみたい場合は、後でアプリケーション ドメインに読み込むことができます。
更新これを試してみました。残念ながら、あなたが遭遇した問題を見つけたと思います。アセンブリがたまたまロードできる場所に書き出されない限り、生成された型の IL バイトを取得する方法はないようです。
リフレクションを介してビットを取得できると思いましたが (クラスは必要なメソッドをサポートしているため)、関連するメソッドThe invoked member is not supported in a dynamic module.
は呼び出し時に例外を発生させるだけです。以下のコードでこれを試すことができますが、要するに、あなたがMarshal::GetFunctionPointerForDelegate()
. 命令をバイナリ ダンプし、IL オペコードとして手動で逆アセンブルする必要があります。ドラゴンがいます。
コードスニペット:
using System;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
using System.Reflection.Emit;
using System.Reflection;
namespace REFLECT
{
class Program
{
private static Type EmitType()
{
var dyn = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Emitted"), AssemblyBuilderAccess.RunAndSave);
var mod = dyn.DefineDynamicModule("Emitted", "Emitted.dll");
var typ = mod.DefineType("EmittedNS.EmittedType", System.Reflection.TypeAttributes.Public);
var mth = typ.DefineMethod("SuperSecretEncryption", System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.Static, typeof(String), new [] {typeof(String)});
var il = mth.GetILGenerator();
il.EmitWriteLine("Emit was here");
il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
il.Emit(System.Reflection.Emit.OpCodes.Ret);
var result = typ.CreateType();
dyn.Save("Emitted.dll");
return result;
}
private static Type TestEmit()
{
var result = EmitType();
var instance = Activator.CreateInstance(result);
var encrypted = instance.GetType().GetMethod("SuperSecretEncryption").Invoke(null, new [] { "Hello world" });
Console.WriteLine(encrypted); // This works happily, print "Emit was here" first
return result;
}
public static void Main (string[] args)
{
Type emitted = TestEmit();
// CRASH HERE: even if the assembly was actually for SaveAndRun _and_ it
// has actually been saved, there seems to be no way to get at the image
// directly:
var ass = AssemblyFactory.GetAssembly(emitted.Assembly.GetFiles(false)[0]);
// the rest was intended as mockup on how to isolate the interesting bits
// but I didn't get much chance to test that :)
var types = ass.Modules.Cast<ModuleDefinition>().SelectMany(m => m.Types.Cast<TypeDefinition>()).ToList();
var typ = types.FirstOrDefault(t => t.Name == emitted.Name);
var operands = typ.Methods.Cast<MethodDefinition>()
.SelectMany(m => m.Body.Instructions.Cast<Instruction>())
.Select(i => i.Operand);
var requiredTypes = operands.OfType<TypeReference>()
.Concat(operands.OfType<MethodReference>().Select(mr => mr.DeclaringType))
.Select(tr => tr.Resolve()).OfType<TypeDefinition>()
.Distinct();
var requiredAssemblies = requiredTypes
.Select(tr => tr.Module).OfType<ModuleDefinition>()
.Select(md => md.Assembly.Name as AssemblyNameReference);
foreach (var t in types.Except(requiredTypes))
ass.MainModule.Types.Remove(t);
foreach (var unused in ass.MainModule
.AssemblyReferences.Cast<AssemblyNameReference>().ToList()
.Except(requiredAssemblies))
ass.MainModule.AssemblyReferences.Remove(unused);
AssemblyFactory.SaveAssembly(ass, "/tmp/TestCecil.dll");
}
}
}
クラスのILだけが必要な場合は、User
すでに持っています。それはあなたがそれをコンパイルしたdllにあります。
他のアセンブリから、クラスを含むdllをUser
動的にロードし、リフレクションを通じて使用できます。
更新:
で作成された動的クラスがあるReflection.Emit
場合は、AssemblyBuilder
それを使用してディスクに保存できます。
代わりに動的タイプがで作成されたMono.Cecil
場合は、(Mono.Cecil 0.9で)AssemblyDefinition
ディスクに保存できるものがあります。myAssemblyDefinition.Write("MyAssembly.dll")