2013-10-16 126 views
2

我想使用LINQ表達式來使用Expression.CompileToMethod方法在類中生成一個實例方法。不允許對這段代碼使用reflection.emit,並且從來沒有使用linq來處理除LCG方法之外的任何東西:(我需要訪問類中的字段。如何使用LINQ表達式訪問「this」?LINQ表達式和這個

Update : 似乎並不像它支持當我試圖通過一個methodbuilder到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");** 
+0

請發佈代碼,以便我們可以更好地瞭解您正在嘗試做什麼。 – mayabelle

+0

我想用linq編譯一些能夠訪問「this」的代碼,非常簡單。不過我會寫一個簡單的例子。 – user1985513

回答

-1

你可以用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 
+0

謝謝,但不是真的我在找什麼。看起來像生成實例方法不支持LINQ表達式。 – user1985513

+0

'Expression.Constant(this)'指的是創建表達式樹的對象。 OP想要一個'this'來引用表達式樹被編譯到的對象。 –