2010-01-07 3 views
0

Это я снова, о моей игре Mega Man. Я переключился на систему компонентов, чтобы объекты могли управляться данными. Все идет нормально, но я столкнулся с проблемой.Как глубоко скопировать объект, содержащий лямбда-выражение?

Мои объекты имеют состояния, заданные входным файлом. Эти государства имеют триггеры для перехода их в другие государства. Условия изменения состояния также находятся во входном файле и анализируются в лямбда-выражение. Теперь мне нужно глубоко скопировать мои объекты, и мне нужно, чтобы лямбды ссылались на членов копии, а не на членов оригинала. Оригиналы загружаются из файла при загрузке программы, но могут быть скопированы в любое время после (подумайте о запуске снарядов).

Вот значительно упрощена бит кода:

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; 
    } 
} 

Там больше, чем это, триггеры на самом деле вызывают изменение состояния, а затем инициализатор нового государства называет это действие, но я упростил его здесь.

Таким образом, проблема заключается в том, что когда я глубоко копирую этот компонент или пытаюсь в любом случае, я не знаю, как это сделать, чтобы lambdas ссылался на экземпляр экземпляра DependentComponent, а не на оригинал. Я уже убедился, что глубокая копия объекта получает новый DependentComponent, но лямбда просто ссылается на оригинал. Является ли делегирование в основном заблокированным для определенных экземпляров после его создания? Должен ли я создать новый? Я не хочу снова загружать весь объект из файла.

ответ

0

Почему бы не сделать это аргументом лямбда?

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

Если вам нужно больше, чем просто один зависимый компонент, вы также можете передать этот указатель, если вы хотите поменять местами лямбды между объектами разных классов, используют интерфейс ...

+0

Я действительно понял это и сделал это не менее 1 минуты после публикации. Но меня все еще интересует, есть ли общее решение этой проблемы. – Tesserex

0

деревьев выражений являются неизменяемыми, поэтому, если в нем есть ссылки на объекты, они будут относиться к исходным объектам. Чтобы глубоко скопировать его, вам понадобится какой-то посетитель с заменой; У меня есть какой-то похожий код где-то, но это большая работа. Конечно, если у него нет, в нем есть ссылки на конкретные объекты, вы можете просто использовать его «как есть» совершенно безопасно.

Предполагаете, вы имеете в виду поле LambdaExpression lambda; Я не знаком с тем, как вы его разбираете, поэтому я не могу прокомментировать, как легко это сделать, но общий параметр здесь заключается в параметризации лямбда; передать целевой объект в качестве аргумента, и вы можете повторно использовать лямбда с несколькими разными объектами во время выполнения (если они относятся к соответствующему типу).

+0

Я думаю, он хочет на самом деле изменить его. Хотя исходная лямбда имеет доступ к локальному свойству, он хочет, чтобы скопированная лямбда достигла свойства нового объекта. –

+0

Точно; поэтому я говорю: lambda доступ к свойству параметра ('Expression.Parameter') и передать' this' в * тот же * (неизменный и неизменный) лямбда в обоих местах. –

+0

Ок, извините, не читал, что далеко ... :-) –

Смежные вопросы