关于我的Mega Man游戏,这又是我。我切换到组件系统,以便对象可以被数据驱动。它没问题,但我遇到了问题。
我的对象具有使用输入文件指定的状态。这些州有触发器将其转移到其他州。状态更改的条件也在输入文件中,并被解析为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;
}
}
除此之外,触发器实际上会导致状态更改,然后新状态的初始化程序会调用该Action,但我在此处对其进行了简化。
所以问题是,当我深度复制这个组件,或者尝试无论如何,我不知道如何使它成为lambda引用副本的DependentComponent实例,而不是原始的实例。我已经确定实体的深层副本正在获取一个新的DependentComponent,但lambda只是引用原始的。委托是否在创建后基本上锁定到特定实例?我需要创建一个新的吗?我不想再次从文件中加载整个实体。
答案 0 :(得分: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,使用一个接口...
答案 1 :(得分:0)
表达式树是不可变的,因此如果它具有对象引用,它们将是原始对象。要深层复制它,你需要一些替代的访客;我在某处有类似的代码,但这是很多工作。当然,如果 中没有具有特定于对象的引用,您可以非常安全地“按原样”使用它。
假设你的意思是LambdaExpression lambda
字段;我不熟悉你是如何解析它的,所以我不能评论它是多么容易,但这里常见的选择是参数化lambda;将目标对象作为参数传递,并且可以在运行时将lambda与多个不同的对象一起使用(只要它们具有适当的类型)。