2010-01-07 79 views
0

這就是我,關於我的洛克人遊戲。我切換到組件系統,以便對象可以被數據驅動。這沒問題,但我遇到了問題。如何深度複製包含lambda表達式的對象?

我的對象有狀態,用輸入文件指定。這些國家有觸發器將它們轉換到其他國家。狀態改變的條件也在輸入文件中,並被解析成一個lambda表達式。現在我需要深度複製我的對象,並且我需要lambdas來引用副本的成員,而不是原始成員。程序加載時,原始文件會從文件中加載,但可以在任何時候複製(認爲是射擊)。

這裏的代碼大大簡化一下:

class StateComponent 
{ 
    // when the whole entity is cloned, it will get a clone of 
    // DependentComponent as well as a clone of this StateComponent. 
    private OtherComponent DependentComponent; 

    // there is a function to register dependencies. The entity that owns 
    // me also owns DependentComponent, and registered it with me. 

    public StateComponent Clone() 
    { 
     // what should I do here to make the lambda deep copied? 
    } 

    public void LoadFromXml(XElement node) 
    { 
     State state = new State(); 
     LambdaExpression lambda = DynamicExpression.ParseLambda(from xml stuff) 
     Delegate condition = lambda.Compile(); 
     Action effect = LoadTriggerEffect(); 
     state.AddTrigger(condition, effect); 

     // add state to my list of states 
    } 

    private Action LoadTriggerEffect() 
    { 
     Action action = new Action(() => { }); 
     if (some stuff from the input file) 
      action +=() => { DependentComponent.Foo(); DependentComponent.Bar = 5; } 

     return action; 
    } 
} 

還有更多比的是,觸發器實際上可能造成的狀態變化,然後將新狀態的初始化調用動作,但我在這裏簡化它。

所以問題是,當我深拷貝這個組件,或者嘗試無論如何,我不知道如何讓lambda表達式引用副本的DependentComponent實例,而不是原始的。我已經確定實體的深層副本正在獲取新的DependentComponent,但lambda只是引用原始的。委託一旦創建就基本鎖定到特定實例?我需要創建一個新的嗎?我不想再從文件中加載整個實體。

回答

0

爲什麼不把它作爲lambda的參數?

Action<OtherComponent> action = new Action<OtherComponent>((null) => { }); 
if (some stuff from the input file) 
    action += x => { x.Foo(); x.Bar = 5; } 

如果您需要更多的則只是一個依賴的組件,您也可以通過this指針,如果你想交換不同類的對象之間的lambda表達式,使用接口...

+0

我其實已經想到了這一點,發佈後不少於1分鐘。但是我仍然對這個問題是否有一個通用的解決方案感興趣。 – Tesserex 2010-01-08 00:17:57

0

表達式樹是不可變的,所以如果它有對象引用,它們將會是原始對象。要深入複製它,你需要某種具有替代的訪問者;我有一些類似的代碼,但這是很多工作。當然,如果它不是中包含特定於對象的引用,那麼您可以非常安全地「按原樣」使用它。

假設您的意思是LambdaExpression lambda字段;我不熟悉你如何解析它,所以我不能評論它是多麼容易做到,但這裏常見的選擇是參數化lambda;傳入目標對象作爲參數,並且您可以在運行時重新使用具有多個不同對象的lambda表達式(只要它們具有適當的類型)。

+0

我想他實際上想要改變它。當原始lambda訪問本地屬性時,他希望複製的lambda訪問新對象的屬性。 – 2010-01-07 20:52:31

+0

正;所以我說:讓lambda訪問參數的屬性('Expression.Parameter'),並在兩個地方將'this'傳入* same(不可變且不變)的lambda表達式。 – 2010-01-07 20:53:34

+0

好的,對不起,沒有讀到那麼遠...... :-) – 2010-01-07 21:20:23