簡體   English   中英

使用反射擺脫函數中的前兩個參數?

[英]Using reflection to get rid of the first two parameters in the function?

我有以下代碼。 因為可以在Action assign (或表達式)中找到信息,因此始終可以使用bP.. = aP..的形式,所以可以使用反射來消除前兩個參數嗎?

class A { .... }; var a = new A { P1 = .... } // class A and B are totally different clas
class B { .... }; var b = new B { P1 = .... } // But they have some properties with the same names
....
AssignAndDoSth(a.P1, b.P1, () => b.P1 = a.P1);

private void AssignAndDoSth<T>(T curr, T prev, Action assign) // assign can be Expression
{
   if (!EqualityComparer<T>.Default.Equals(curr, prev))
   {
       assign();
       Do(prev);
       ....
   }
}

簡短的回答是“我強烈建議不要這樣做”; 實際上,這實際上是編譯器生成的捕獲類的實例方法。 因此您需要解構目標方法的IL,並根據目標實例的字段評估該IL。 不好。 實際看起來是這樣的:

var ctx = new SomeType();
ctx.a = new A { P1 = .... };
ctx.b = new B { P1 = .... };
AssignAndDoSth(a.P1, b.P1, new Action(ctx.SomeMethod));
...
class SomeType {
    public A a;
    public B b;
    public void SomeMethod()
    {
        b.P1 = a.P1;
    }
}

另一種方法是重構一個Expression<Action> -但這並不改變所涉及的工作 -它只是提出了一個更友好的API(相對而言)。

無論哪種方式,所有這些檢查都將帶來不小的性能成本。

表達式樹可能不包含賦值運算符,但可以包含運算符==

  static void AssignAndDoSomething<T>(T curr, T prev, Expression<Func<bool>> assign)
  {
    var logExpr = assign.Body as System.Linq.Expressions.BinaryExpression;
    //output rid of the first parameter
    Console.WriteLine(logExpr.Left);
    //output rid of the second parameter
    Console.WriteLine(logExpr.Right);
    //assign first parameter
    Expression.Lambda<Action>(Expression.Assign(logExpr.Left, Expression.Constant(curr))).Compile()();
    //assign second parameter
    Expression.Lambda<Action>(Expression.Assign(logExpr.Right, Expression.Constant(prev))).Compile()();
  }
  class A
  {
    public int P1;
  }
  class B
  {
    public int P1;
  }

  var a = new A();
  var b = new B();
  AssignAndDoSomething(a.P1, b.P1, () => b.P1 == a.P1);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM