LINQ 表达式和这个

本文关键字:表达式 LINQ | 更新日期: 2023-09-27 18:35:45

我想使用 LINQ 表达式在 Expression.CompileToMethod 方法的类中生成实例方法。不允许将 reflection.emit 用于这段代码,并且从未将 linq 用于除 LCG 方法之外的任何内容:(我需要访问类中的一个字段。如何使用 LINQ 表达式访问"this"?

更新:似乎不受支持。当我尝试将方法生成器传递到非静态的 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");**

LINQ 表达式和这个

你可以

只使用Expression.Constant

var thisExpr = Expression.Constant(this);
var fieldExpr = Expression.Field(thisExpr, "fieldName");

例如

public class ExprTest
{
    private readonly int value;
    public ExprTest(int value)
    {
        this.value = value;
    }
    public Func<int> GetValueExpr()
    {
        var fieldExpr = Expression.Field(Expression.Constant(this), "value");
        var lambda = Expression.Lambda<Func<int>>(fieldExpr);
        return lambda.Compile();
    }
}
var e = new ExprTest(5);
int i = e.GetValueExpr()();    //i == 5