c# - C# 方法可观察
问题描述
我有一个方法,每当发生事情时都会调用它。它可以被调用任意次数。然后方法返回一个任务。基本上,我想在调用此方法时设置一个“可观察的”。我无法控制被调用的方法。被调用的方法是虚拟的,所以我可以覆盖它以查看它是否被调用。但我宁愿设置一个“可观察的”。所以我有类似的东西
class Foo
{
void Bar()
}
同样,我无法控制 Foo 但我有它的一个实例。
var instanceofFoo = new Foo();
我想设置一个“可观察的”,它会在任何时候instanceOfFoo.Bar
被调用。
我想要一个“可观察”的原因是因为我不想为可能的下一次调用再次设置“观察者”。我正在用 C# 进行编码,我查看了它IObservable<T>
,IObserver<T>
但它特别指出“提供者”必须实现IObservable<T>
. 由于我无法控制提供者(在本例中为 Foo 的实例),因此我无法使用它。我查看了 Rx.NET,但无法从示例中收集到适合这种情况的内容。更复杂的事情假设 Foo 的实例是另一个类的依赖项,例如
class FooService
{
public bool wasCalled { get; set; }
public FooService(Foo f)
{
// TODO: Setup code to trigger when f.Bar() is called
}
}
此设置需要能够被彻底拆除,以便没有悬空的“订阅者”。
所以流程会是这样的
- var foo = new Foo();
- var fooService = new FooService(foo);
- foo.Bar();
- Assert.IsTrue(fooService.wasCalled);
想法?
解决方案
我不确定你为什么专注于“observables”,但是 C# 已经有一个订阅者/发布者类型的交互系统,即events。
您可以使用代理模式结合继承来实现您想要的:
class FooEventProxy : Foo
{
public event EventHandler BarCall;
/*
* Retype all constructors of Foo here and delegate them to base.
*/
public override void Bar()
{
OnBarCall(new EventHandler());
base.Bar();
}
protected virtual void OnBarCall(EventHandler e)
{
EventHandler event = BarCall;
if (event != null)
{
event(this, e);
}
}
}
这是假设您控制创建Foo
并可以强制使用它创建的所有位置FooEventProxy
。
如果你不能,那么你只是找到了将所有创建逻辑保留在工厂中的原因,情况有点复杂。如果您可以访问Foo
它所实例化的所有参数,您可能只需将它们复制到FooEventProxy
. 如果你不能,那么我们就陷入了一个难题:你想用 替换类型的参数Foo
,FooEventProxy
但你不能确保参数的内部状态将正确地转移到新实例中。您不能只将虚拟方法调用路由到包装的实例,因为非虚拟方法仍然可以调用并且无法正常工作 - 违反了 Liskov 原则。因此,您需要将内部状态Foo
完全复制到FooEventProxy
使用大量反射巫毒,或者,你运气不好,你刚刚发现了依赖接口/抽象而不是具体类的原因。
我不知道如何将所有基类数据从现有实例复制到我头顶的派生类型的新实例,所以如果你真的认为这是你想要的,请专门为此提出另一个问题。
推荐阅读
- javascript - 在输入字段中使用 dd/mm/yyyy 输入日期格式
- java - 无法与 OnClick\OnItemClickListener 中的视图及其事件交互
- neo4j - 从记录列表中创建节点时,如何传递 datetime 属性?
- java - 如何将类的对象分配给值
- flask - 用户的烧瓶个人资料页面
- java - 更改片段 - 如果可能,请改进它
- matlab - x * x ^ T的Matlab符号计算
- c# - 如果字符是大写,则拆分 camelCase str 正则表达式?
- c# - 使用排序算法在 Unity 中说明球的排序过程
- python - tensorflow conv2d的padding策略是什么?