首页 > 解决方案 > 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
    }
}

此设置需要能够被彻底拆除,以便没有悬空的“订阅者”。

所以流程会是这样的

  1. var foo = new Foo();
  2. var fooService = new FooService(foo);
  3. foo.Bar();
  4. Assert.IsTrue(fooService.wasCalled);

想法?

标签: c#observable

解决方案


我不确定你为什么专注于“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. 如果你不能,那么我们就陷入了一个难题:你想用 替换类型的参数FooFooEventProxy但你不能确保参数的内部状态将正确地转移到新实例中。您不能只将虚拟方法调用路由到包装的实例,因为非虚拟方法仍然可以调用并且无法正常工作 - 违反了 Liskov 原则。因此,您需要将内部状态Foo完全复制到FooEventProxy使用大量反射巫毒,或者,你运气不好,你刚刚发现了依赖接口/抽象而不是具体类的原因。

我不知道如何将所有基类数据从现有实例复制到我头顶的派生类型的新实例,所以如果你真的认为这是你想要的,请专门为此提出另一个问题。


推荐阅读