C# 注册未知生存期的实例
假设我们有3个不同的程序集 通用组件C# 注册未知生存期的实例,c#,design-patterns,optimization,C#,Design Patterns,Optimization,假设我们有3个不同的程序集 通用组件 公共抽象类ContextBase { } 公共抽象类ContextManager,其中T:ContextBase { //包含所有上下文管理逻辑。 公共T FindContext() { // ... } } 特定于应用程序的程序集2: 公共类SpecialContext:ContextBase { //特定于此类型上下文的自定义属性 } 公共类SpecialContextManager:ContextManager { //继承其基类的大部分逻辑,但
公共抽象类ContextBase
{
}
公共抽象类ContextManager,其中T:ContextBase
{
//包含所有上下文管理逻辑。
公共T FindContext()
{
// ...
}
}
特定于应用程序的程序集2:
公共类SpecialContext:ContextBase
{
//特定于此类型上下文的自定义属性
}
公共类SpecialContextManager:ContextManager
{
//继承其基类的大部分逻辑,但有一些
//重写以实现稍微不同的行为
}
特定于应用程序的程序集3:
public类OtherContext:ContextBase
{
//特定于此类型上下文的自定义属性
}
公共类OtherContextManager:ContextManager
{
//继承其基类的大部分逻辑,但有一些
//重写以实现稍微不同的行为
}
抽象泛型ContextManager类的动机是,每个ContextManager都保留一个特定于给定类型T的对象的静态集合。当然,您可以执行类似Dictionary>的操作。。但我更喜欢通用基类方法
问题
现在我想制作一个GUI来显示/查找所有上下文。这意味着各种语境。
我不想为每个应用程序集中的每个应用程序编写GUI。
我想到了一个“通用GUI”,它向我显示所有当前活动的上下文,不管它们是什么类型(虽然在GUI中显示一些更详细的信息,但知道它们的类型会很酷)。很明显,我可以使用相应的ContextManager实例找到所有的上下文,但是如何掌握它们呢
这就是我的想法(并因设计不好而被拒绝):
公共静态类CmInstanceMonitor
{
私有静态列表_contextMgrs=新列表;
公共静态无效注册表状态(ContextManager cm)
{
//也许我应该确保不添加同一个对象两次
//不幸的是,在调用此方法时,我还不能使用该类型
//通过基类ctor():(
_contextMgrs.Add(cm);
}
}
这样,我的ContextManager可能永远存在,因为静态对象保存了对它的引用。这不是我想要的。而且,将一些代码放入ContextManager终结器可能不会有任何好处,因为静态引用不会对对象进行GC
我卡住了!:)你可以用。这允许您维护所有管理器的列表,而不会影响垃圾收集
然而,在这种情况下,使用泛型有一些缺点。类SpecialContextManager
可以强制转换为ContextManager
。那很好。但是,此类不能转换为ContextManager
,因为它们是两个不同的类。因此,你不能打电话
RegisterInstance(ContextManager)
传递一个具体的管理器。因此,您可以在列表中存储对象
(或WeakReferences
到对象
),或者使用不同的方法(例如,通过反射获取所有类)。但是,在某种程度上,检索所有管理器的方法的返回类型必须是object
。您可以使用。这允许您维护所有管理器的列表,而不会影响垃圾收集
然而,在这种情况下,使用泛型有一些缺点。类SpecialContextManager
可以强制转换为ContextManager
。那很好。但是,此类不能转换为ContextManager
,因为它们是两个不同的类。因此,你不能打电话
RegisterInstance(ContextManager)
传递一个具体的管理器。因此,您可以在列表中存储对象
(或WeakReferences
到对象
),或者使用不同的方法(例如,通过反射获取所有类)。但是,在某种程度上,检索所有管理器的方法的返回类型必须是object
public abstract class ContextBase
{
}
public abstract class ContextManager<T> where T: ContextBase
{
// contains all the context managing logic.
public T FindContext()
{
// ...
}
}
public class SpecialContext : ContextBase
{
// custom properties specific to this type of context
}
public class SpecialContextManager : ContextManager<SpecialContext>
{
// inherits most of the logic from its base class but has some
// overrides to achieve a slightly different behavior
}
public class OtherContext : ContextBase
{
// custom properties specific to this type of context
}
public class OtherContextManager : ContextManager<OtherContext>
{
// inherits most of the logic from its base class but has some
// overrides to achieve a slightly different behavior
}
public static class CmInstanceMonitor
{
private static List<ContextManager<ContextBase>> _contextMgrs = new List<ContextManager<ContextBase>>;
public static void RegisterInstance(ContextManager<ContextBase> cm)
{
// probably I should make sure I don't add the same object twice
// unfortunately I cannot use the Type yet as this method is invoked
// by the base class ctor() :(
_contextMgrs .Add(cm);
}
}