我在我的游戏中增加了一个重放功能。有了这个功能,我可以捕获用户对游戏的输入,并在稍后将其反馈给团结,以便重新播放游戏。但是VRStandardAssets.Utils.VRInput类的设计阻止了我模拟用户输入。
该类不提供任何公共方法来以编程方式触发其事件(例如OnClick或OnDoubleClick事件)。因此,我决定从它创建一个派生类,并编写自己的公共方法来触发事件。这个策略失败了,因为VRInput的方法是私有的,这意味着我不能从派生类调用它们。
对于这种类型的类,建议为eventName方法提供了一个受保护的虚拟空,为派生类提供了一种使用重写来处理事件的方法,但是这个类没有它(为什么有这么多限制?)我想这是联合公司的一个糟糕的设计。这种糟糕的设计也使得编写单元/集成测试变得困难。
我是不是漏掉了什么?我还能做些什么来欺骗其他类,让他们在重放游戏时认为他们在处理VRInput类吗?
发布于 2018-04-26 14:25:30
实际上,可以从另一个类和触发这些事件(OnClick、OnDoubleClick或任何其他事件),而无需使用反射(使用这种聪明的黑客(受这篇文章的启发)):
C#并不是真正的类型安全,所以您可以共享相同的内存位置。首先,使用共享相同内存空间的两个字段声明一个类:
[StructLayout(LayoutKind.Explicit)]
public class OverlapEvents
{
[FieldOffset(0)]
public VRInput Source;
[FieldOffset(0)]
public EventCapture Target;
}然后,您可以声明一个新的类,它将拦截并调用另一个事件:
public class EventCapture
{
public event Action OnClick;
public void SimulateClick()
{
InvokeClicked();
}
// This method will call the event from VRInput!
private void InvokeClicked()
{
var handler = OnClick;
if (handler != null)
handler();
}
}然后最后注册并调用它:
public static void Main()
{
input = GetComponent<VRInput>();
// Overlap the event
var o = new OverlapEvents { Source = input };
// You can now call the event! (Note how Target should be null but is of type VRInput)
o.Target.SimulateClick();
}下面是一个简单的dotNetFiddle,它显示了它的工作(至少在统一之外)。
发布于 2018-04-26 01:59:43
建议这种类型的类在eventName方法上提供受保护的虚拟空,以便为派生类提供一种使用覆盖来处理事件的方法,但是这个类没有它(为什么有这样的限制?)我想这是联合公司的一个糟糕的设计。这种糟糕的设计也使得编写单元/集成测试变得困难。
所有代码都是好代码。所有代码也都是坏代码。取决于你的评估标准。团结的开发人员可能没有考虑到您的用例。作为另一个相互冲突的经验法则,软件也应该尽可能的简单和僵化,因此,在没有已知用例的情况下预测子类可能会被认为是过度工程。
关于如何解决这个问题,请参见如何通过.NET/C#中的反射引发事件?。
https://stackoverflow.com/questions/49865143
复制相似问题