我有实体的类,例如ShipShampooHorse等,它们每个都有一个管理器类,例如ShipManagerShampooManagerHorseManager等。所有管理器类都实现IManager和实体实现IEntity

现在,我编写了一个静态函数来保存实体,如下所示:

public static bool Save<S, T>(S entity, string msg) where S : IEntity
                                                    where T : IManager<S>, new()
{
    string possibleError;
    switch (new T().Save(entity, out possibleError))
    {
        //---------------------
    }
    return true;
}


这里的优雅之处在于,我必须像Save等那样称呼Save<Radio, RadioManager>。我希望拥有的是这样的东西:

public static bool Save<T>(T entity, string msg) where T : IEntity
{
    string possibleError;
    switch ((/*find manager here*/).Save(entity, out possibleError))
    {
        //---------------------
    }
    return true;
}


这样做的方法很少,但是我很想拥有涉及泛型和类型推断的内容。我认为将实体类与相应的管理器类通过设计耦合以实现某种类型的安全性也将是很好的。

在扩展方法的帮助下,这是我可以做的:

public static bool Save<T>(this IManager<T> mgr, T entity, string msg) where T : IEntity
{
    string possibleError;
    switch (mgr.Save(entity, out possibleError))
    {
        //---------------------
    }
    return true;
}


这样我可以打电话给:

FooManager fMgr = new FooManager();
fMgr.Save(foo, "success");


但是在这里,我总是需要实例化IManager,然后在其实例上调用Save方法。我很想避免那么多重复的代码,而将职责交给静态函数。如何设计类以在IManagerIEntity之间建立关系,以便自动推断实体管理器?

编辑:请注意,我没有奢侈地将管理器类中的Save方法移动到实体类(这将使生活更轻松)。我们的整个设计基于一个实体类和一个相应的经理类。所以我正在考虑坚持下去。

最佳答案

FooManager的客户端是否关心它是FooManager还是IManager ?如果只需要IManager ,则可能要查看AbstractFactory模式。您的工厂将负责按需实例化/检索正确的IManager。有了工厂,您的保存方法将如下所示

public static bool Save<S>(S entity, string msg)
  where S : IEntity
  {
     string possibleError;
     switch (ManagerFactory.GetManagerFor<S>().Save(entity, out possibleError))
     {
       //---------------------
     }
     return true;
  }


实现ManagerFactory的最简单方法是使用服务定位器/依赖项注入器,并使其自动发现IManager 实现。然后,您的GetManagerFor方法将只从DI容器中请求一个实例。例如,以下是使用AutoFac的方法

var dataAssembly = Assembly.GetExecutingAssembly();

builder.RegisterAssemblyTypes(dataAssembly)
    .Where(t => t.Name.EndsWith("Manager"))
    .AsClosedTypesOf(typeof(IManager<>);


这将导致autofac在当前程序集中查找名称中以“ Manager”结尾的所有类,并注册为IManager 的封闭类型。因此它将找到FooManager并将其注册为IManager 的实例。

现在ManagerFactory只需要调用

return container.Resolve<IManager<Foo>>()


而且你很黄金。我不会为您编写您的应用程序,但这应该给您足够的帮助。阅读AutoFac上的文档,它确实功能强大,因为它也可以使用依赖注入为您建立对象,并且它是您掌握的绝佳工具。

关于c# - 如何以通用方式耦合两个类?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12924077/

10-09 03:27