循环泛型类型参数
本文关键字:泛型类型参数 循环 | 更新日期: 2023-09-27 18:14:35
我有2个通用类,一个BaseComponent
类和一个BaseManager
类。
它们都是抽象的,都是要具体化的。
public abstract class BaseManager<T> where T : BaseComponent<?>
public abstract class BaseComponent<T> where T : BaseManager<?>
BaseManager
有一个BaseComponents列表,这就是为什么我想让它通用,所以PhysicsManager : BaseManager<PhysicsComponent>
会有一个PhysicsComponents
列表。
我想(或者更确切地说,我认为我需要)BaseComponent
是通用的,因为我只希望从BaseComponent
派生的类被"附加"到它们适当的管理器。理想情况下,我不想为每个派生组件编写构造函数,这样我就可以将其添加到传入的具体管理器类中。理想情况下,我想有一个构造函数,接受抽象的BaseManager
类。
我如何管理这种循环依赖?
听起来您可能希望有两个泛型类型参数:
public abstract class BaseManager<TComponent, TManager>
where TComponent : BaseComponent<TComponent, TManager>
where TManager : BaseManager<TComponent, TManager>
public abstract class BaseComponent<TComponent, TManager>
where TComponent : BaseComponent<TComponent, TManager>
where TManager : BaseManager<TComponent, TManager>
是的,它很臭-但这就是我在协议缓冲区中所做的事情。
然后是:
public class PhysicsManager : BaseManager<PhysicsComponent, PhysicsManager>
public class PhysicsComponent : BaseComponent<PhysicsComponent, PhysicsManager>
最松散的耦合是组件不知道它们的管理器。这里有一个例子说明它是如何工作的。请注意,如果必须将所有组件添加到管理器中,则此方法需要某种工厂机制。(Nat Pryce - "如果两个物体之间存在某种关系,那么其他物体应该建立这种关系。")
abstract class BaseComponent
{
public event EventHandler SomethingHappened;
}
abstract class BaseManager<TComponent> where TComponent : BaseComponent
{
List<TComponent> components = new List<TComponent>();
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<TComponent> : 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<PhysicsComponent>, IPhysicsManager
{
protected override void ManageMe(PhysicsComponent component)
{
throw new NotImplementedException();
}
public void AnotherCallback(PhysicsComponent comp)
{
throw new NotImplementedException();
}
}
缺点是类型系统不强制传入正确的管理器,并且BaseManager中的强制转换会失败。我仍然喜欢这种方式,"在我的基础设施中保持气味",而不是让循环模板污染我所有的具体组件和管理器。