4

Expression.CompileToMethod メソッドを使用して、LINQ 式を使用してクラスにインスタンス メソッドを生成したいと考えています。このコードにreflection.emitを使用することは許可されておらず、LCGメソッド以外にlinqを使用したことはありません:(クラスのフィールドにアクセスする必要があります。LINQ式を使用して「これ」にアクセスするにはどうすればよいですか?

更新:サポートされているようには見えません。メソッドビルダーを静的ではない CompileToMethod に渡そうとすると、引数の例外が発生します。linq式は静的メソッドの作成にのみ使用できることを誰かが確認できますか?

AssemblyName asmName = new AssemblyName("foo");
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
                asmName,
                AssemblyBuilderAccess.RunAndCollect);


            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("foo");
            TypeBuilder typeBuilder = moduleBuilder.DefineType(
                "foo",
                TypeAttributes.Public,
                typeof(object));

            FieldInfo field = typeBuilder.DefineField("FooBar", typeof(string), FieldAttributes.Private);
            ConstructorBuilder constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(string) });

            // want to use linq expressions for constructor too.
            ILGenerator generator = constructor.GetILGenerator();
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
            generator.Emit(OpCodes.Ldarg_0);
            generator.Emit(OpCodes.Ldarg_1);
            generator.Emit(OpCodes.Stfld, field); 
            generator.Emit(OpCodes.Ret);

            MethodBuilder method = typeBuilder.DefineMethod("Bar", MethodAttributes.Public | MethodAttributes.Static);

            Expression writeLine = Expression.Call(
                null,
                typeof(Console).GetMethod("WriteLine", BindingFlags.Public | BindingFlags.Static, null, new Type[] { typeof(string), typeof(object) }, null),
                Expression.Constant("The value is {0}"),
                Expression.Constant("no this")); //Expression.MakeMemberAccess("this", field)); // need to access this.

            Expression.Lambda<Action>(
                writeLine).CompileToMethod(method);


            Type myType = typeBuilder.CreateType();
            object instance = Activator.CreateInstance(myType, "FooBar");
            MethodInfo barMethod = myType.GetMethod("Bar", BindingFlags.Static | BindingFlags.Public);
            barMethod.Invoke(instance, null);

更新 2: サポートされていないようです

private void CompileToMethodInternal(MethodBuilder method, DebugInfoGenerator debugInfoGenerator)
{
  ContractUtils.RequiresNotNull(method, "method");
  **ContractUtils.Requires(method.IsStatic, "method");**
4

1 に答える 1