2010-12-06 31 views
4

據我所知,沒有辦法與表達式樹中的引用類型進行交互。 (例如沒有發出stind.*ldind.*操作碼)。 我正在研究一些重寫器來解決這個問題。由於我構建了一個新的類型,其方法體已由委託調用取代(以解決CompileToMethod只能執行不能與新成員交互的靜態方法的事實)。對於by-ref和out參數,我想我會用StrongBox<T>來替換它們的用法。使用IL分配給ref的字段是否合法?

所以,如果我碰到有看起來像這樣::一個簽名的方法來

public class SomeClass 
{ 
    public virtual bool SomeMethod(string arg1,ref int arg2) 
    { 
    } 
} 

的倍率,該callbase方法,並委託我場產生看起來像這樣::

public class SomeClass<1> : SomeClass 
{ 
    private static bool SomeMethod<0>(
      SomeClass target,string arg1,StrongBox<int> arg2) 
    { 
     return call target.SomeMethod(arg1,ref arg2.Value) 
    } 

    private Func<SomeClass,string,StrongBox<int>,bool> <0>SomeMethod; 

    public override bool SomeMethod(string arg1,ref int arg2) 
    { 
     StrongBox<int> box = new StrongBox<int>(); 
     box.Value = arg2; 
     bool retVal = <0>SomeMethod.Invoke(this,arg1,box); 
     arg2 = box.Value; 
     return retVal; 
    } 
} 

但是,這是相當多的代碼來執行此轉換,對於每個參數它引入了很多複雜性。當我執行box.Value = arg2的設置時,如果我可以執行類似&box.Value = &arg2這樣的操作,它會將地址分配給arg2的地址。這樣,當委託在值字段上執行變更時,變更就會被轉發。這樣做意味着我不需要有一個變量來保存返回值,並且我不需要執行參考值更新。

或者,如果有一種方法可以通過表達式樹來執行帶引號分配的語義,當然,我都是耳朵。

+0

這讓我想起了Eric Lippert的[Ref Class](http://stackoverflow.com/questions/2980463/how-do-i-assign-by-reference-to-a-class-field-in-c/2982037#2982037)。 – Brian 2010-12-06 17:14:57

回答

0

不知道如果我真的能理解,但也許這是一個解決方案:

class Program 
{ 

    public class SomeClass 
    { 
     private readonly int _n; 

     public SomeClass(int n) { _n = n; } 

     public virtual bool SomeMethod(string arg1, ref int arg2) { 
      if (String.IsNullOrWhiteSpace(arg1)) return false; 
      arg2 += arg1.Length + _n; 
      return true; 
     } 
    } 

    private delegate bool SomeDelegate(SomeClass that, string arg1, ref int arg2); 

    static void Main(string[] args) { 
     var instance = Expression.Parameter(typeof (SomeClass), "that"); 
     var arg1Param = Expression.Parameter(typeof(string), "arg1"); 
     var arg2Param = Expression.Parameter(typeof (int).MakeByRefType(), "arg2"); 
     var someMethodInfo = typeof (SomeClass).GetMethod("SomeMethod"); 
     var lambda = Expression.Lambda<SomeDelegate>(Expression.Call(instance, someMethodInfo, arg1Param, arg2Param), instance, arg1Param, arg2Param); 
     var someDelegate =lambda.Compile(); 
     var myClass = new SomeClass(2); 
     var arg1 = "yup"; 
     var arg2 = 1; 
     var result = someDelegate(myClass, arg1, ref arg2); 
     if(arg2 != 6) throw new Exception("Bad!"); 
     Console.WriteLine("works..."); 
    } 

} 

我覺得最重要的一點是typeof (int).MakeByRefType()

相關問題