如何在不知道对象调用者类的情况下订阅对象?

问题描述 投票:0回答:1

我有一个Scenario,它使用A或几个AsA是在此[[Scenario之外创建的,但在A内部创建的B却不知道该实例的场景。这就是想法,A和B不必知道场景的工作原理,它们只需要在引发/调用UpdateEvent时工作。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp { class Program { static void Main(string[] args) { var sce1 = new Scenario(); sce1.Add(new A(1)); sce1.Add(new A(3)); sce1.Update(2); sce1.Update(5); var sce2 = new Scenario(); sce2.Add(new A(6)); sce2.Update(0.3); Console.ReadKey(); } } public class BasicEvent : EventArgs { public double Number { get; set; } } public abstract class toBeUpdated { public abstract void OnUpdate(object sender, BasicEvent e); } public class C : toBeUpdated { public double Number { get; set; } public C(double num) { Number = num * num; } public override void OnUpdate(object sender, BasicEvent e) { Number = Math.Pow(e.Number, 2); } } public class B : toBeUpdated { public double Number { get; set; } public B(double num) { Number = num; } public override void OnUpdate(object sender, BasicEvent e) { Number *= e.Number; } } public class A : toBeUpdated { private B B1 { get; set; } private B B2 { get; set; } private C C1 { get; set; } public A(double number) { B1 = new B(number); B2 = new B(number); C1 = new C(number); } public override void OnUpdate(object sender, BasicEvent e) { Console.WriteLine($"Updating A.. Data = {B1.Number + B2.Number * C1.Number}"); } } public class Scenario { private event EventHandler<BasicEvent> UpdateEvent; private List<toBeUpdated> toKeepTrack { get; set; } public Scenario() { toKeepTrack = new List<toBeUpdated>(); } public void Add(toBeUpdated obj) { toKeepTrack.Add(obj); UpdateEvent += obj.OnUpdate; } public void doSomethingWithTheList() { .... } public void Update(double num) { UpdateEvent?.Invoke(this, new BasicEvent() { Number = num }); Console.WriteLine(); } } }
我需要创建几种方案,我不能使其成为静态。
c# events architecture event-handling structure
1个回答
0
投票
对于此用例,我认为最好的方法是创建一个接口IScenario,并让Scenario扩展此接口。这将

隐藏 Scenario的实现细节,并允许您将IScenario直接传递到A的构造函数中。

public interface IScenario { void Add(toBeUpdated obj); void Update(int num); }
您现在可以像这样扩展Scenario

public class Scenario : IScenario { ... }

相应地更新A

public class A : toBeUpdated { ... public A(int number, IScenario scenario) { B1 = new B(number); scenario.Add(this); scenario.Add(B1); } ... }

如何使用将类似于:

var sce = new Scenario(); A a1 = new A(1, sce); A a3 = new A(3, sce); sce.Update(2); sce.Update(5);

此方法可确保A不知道Scenario正在以最小的努力进行更新,并且该方法是可测试的。另一种方法是在A上添加一个方法,该方法

registers

Scenario(如果A在创建后需要添加新的Scenario,则很有用):public void Register(IScenario scenario) { scenario.Add(this); scenario.Add(B1); }

注意:创建IScenario不是必需

,但是当您进入unit testing并想要mock对象时,最好具有它。
© www.soinside.com 2019 - 2024. All rights reserved.