循环generics类型参数

我有2个generics类,一个BaseComponent类和一个BaseManager类。

它们既抽象又有意成为具体的。

 public abstract class BaseManager where T : BaseComponent public abstract class BaseComponent where T : BaseManager 

BaseManager有一个BaseComponents列表,这就是为什么我想让它成为通用的,所以PhysicsManager : BaseManager会有一个PhysicsComponents列表。

我想(或者更确切地说,我认为我需要) BaseComponent是通用的,因为我只希望从BaseComponent派生的类“附加”到它们适当的管理器。 理想情况下,我不想为每个派生组件编写构造函数,因此我可以将它添加到传递的具体管理器类中。 理想情况下,我想要一个采用抽象BaseManager类的构造函数。

我怎样才能管理这种循环依赖?

听起来你可能想要两个generics类型参数:

 public abstract class BaseManager where TComponent : BaseComponent where TManager : BaseManager public abstract class BaseComponent where TComponent : BaseComponent where TManager : BaseManager 

是的,这很臭 – 但这就是我在Protocol Buffers中所做的事情。

那你就得:

 public class PhysicsManager : BaseManager public class PhysicsComponent : BaseComponent 

最松散的耦合是组件不知道他们的经理。 这是一个如何工作的例子。 请注意,如果必须将所有组件添加到管理器,则此方法需要某种工厂机制。 (Nat Pryce – “如果两个对象之间存在关系,那么其他一些对象应该建立关系。” )

 abstract class BaseComponent { public event EventHandler SomethingHappened; } abstract class BaseManager where TComponent : BaseComponent { List components = new List(); public virtual void AddComponent(TComponent component) { components.Add(component); component.SomethingHappened += (s, e) => OnSomethingHappened(component); } public abstract void OnSomethingHappened(TComponent component); } 

如果组件不能独立于其管理器,我认为它们依赖于由组件需求定义的接口会更好。 这是接口隔离原则

 interface IManager { void ManageMe(BaseComponent component); } abstract class BaseComponent { public BaseComponent(IManager manager) { manager.ManageMe(this); } } abstract class BaseManager : IManager where TComponent : BaseComponent { void IManager.ManageMe(BaseComponent component) { ManageMe((TComponent)component); } protected abstract void ManageMe(TComponent component); } interface IPhysicsManager : IManager { void AnotherCallback(PhysicsComponent comp); } abstract class PhysicsComponent : BaseComponent { public PhysicsComponent(IPhysicsManager manager) : base(manager) { manager.AnotherCallback(this); } } abstract class PhysicsManager : BaseManager, IPhysicsManager { protected override void ManageMe(PhysicsComponent component) { throw new NotImplementedException(); } public void AnotherCallback(PhysicsComponent comp) { throw new NotImplementedException(); } } 

缺点是类型系统不强制传入正确的管理器,然后BaseManager中的强制转换失败。 我仍然更喜欢这种方式并“在我的基础设施中保持气味”,而不是让圆形模板污染我所有的具体组件和管理人员。