3

我有像Ship,等实体的类,它们每个都有一个像Shampoo,等的管理器类。所有管理器类都实现和实体实现。HorseShipManagerShampooManagerHorseManagerIManagerIEntity

现在我写了一个静态函数来保存看起来像这样的实体:

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管理器类中的方法移动到实体类的奢侈(这会使生活更轻松)。我们的整个设计基于一个实体类和一个相应的管理器类。所以我想坚持下去。

4

2 回答 2

4

FooManager 的客户是否关心它是 FooManager 还是 IManager<Foo> ?如果它只需要一个 IManager<Foo>,您可能需要查看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<T> 实现。然后您的 GetManagerFor 方法只会从 DI 容器中请求一个实例。例如,这里是使用AutoFac的方法

var dataAssembly = Assembly.GetExecutingAssembly();

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

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

现在 ManagerFactory 只需要调用

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

而你是金色的。我不会为你写申请,但这应该足以让你继续前进。阅读 AutoFac 上的文档,它真的很强大,因为它还可以使用依赖注入为您构建对象,并且它是一个很好的工具。

于 2012-10-16T22:09:02.260 回答
0

这是我解决它的方法。

Manager我像这样创建了一个函数IEntity

IManager<T> Manager<T>() where T : IEntity;

现在,每当我IEntity在任何实体类中实现时,我也被迫实现它们各自Manager的。例如。

public class Foo : IEntity
{
    public IManager<T> Manager<T>() where T : IEntity
    {
        return (IManager<T>)new FooManager();
    }
}

现在我可以打电话了:

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

不是最好的设计,但这可以完成工作..

于 2012-10-18T14:17:10.200 回答