1

我很难理解 Ioc 和泛型,尤其是我的公司如何设置与此相关的层。我们在 MVP 架构下工作。

我有一个汽车课:

class Car : ICar
{
   IList<IWheel> wheels{get;set;}
   IEngine engine{get;set;}
   string registrationplate {get;set;}

   public Car(){}
}

并且我希望能够获得一个新创建的 ICar,并且我还希望能够通过 Id 找到 ICar。问题是我不确定为什么在我正在进行的项目中做出了一些设计选择。已经创建的其他服务的结构如下:

我有汽车和车轮服务:

class WheelService : BaseService
{
    IWheel wheel;

    public IWheel Create()
    {
        return new wheel()
    }

 }
class CarService : BaseService
{
   WheelService wheelservice;

   public ICar CarCreate()
   {
     wheelservice = new Wheelservice()
     car = new Car();
     IWheel wheel = wheelservice.Create();
     car.wheels.add(wheel);
     return car;
   }

   public ICar Find(int id)
   {
        return (Car)base.Find<Car>(id);
   }

}
  1. 首先,我发现“为每个实体提供服务”很奇怪。我不会想到一个弱实体会有服务。我的想法是 CarService create 方法将像工厂方法一样工作,而无需调用车轮服务。
    此外,在演示者代码中实际上使用了轮服务创建方法,以将 IWheel 一直返回到 UI,以便可以设置值并向上传递。再一次,这对我来说似乎很奇怪。表示演示者可以从 UI 请求完整的 ICar 对象。

  2. Service create方法中的依赖是否正常?我原以为这将通过 IoC 引入。但是,如果 ICar Create 方法要处理所有创建(包括轮子等),那么大概容器将包含许多与此特定服务相关的接口?

  3. 如果我要引入接口,我需要调整 CarService.Find 方法,该方法目前正在使用具体类。它使用 BaseService,并且只有这一层与容器交互以获得正确的存储库:

class BaseService
{
private object myRepository;

 protected T GetRepository<T>(Type serviceType)
    {

        if (myRepository == null)
        {
            myRepository = (T)IoCRepositoryFactory.GetRepositoryInstance(typeof(T), serviceType);
        }
        return (T)myRepository;
     }


protected virtual IGenericRepository Repository
    {
        get
        {
            return GetRepository<IGenericRepository>(this.GetType());
        }
    }

protected virtual T Find<T>(Object id) where T : class
    {
        return (T)Repository.GetByID<T>(id);
    }

}

如果我只使用接口,我不确定如何调用这个 find 方法,因为当前的服务定义正在使用具体的类。

抱歉,这是一个冗长的帖子。我已经查看了三天,但我需要知道其他人对当前设置的看法,以及我是否应该将 IOC 用于服务层中的域对象,或者我是否应该遵循当前设置。此刻对我来说,这一切都感觉有点耦合。

4

1 回答 1

0

我想你有很多误解。

我将从服务结构开始。您不必让每个服务只处理一种类型的实体,但只要不妨碍效率就没有错。您的示例可能过于简单化,因此您可能可以让 CarService 处理车轮管理,而不会出现任何未来的维护问题,但是按实体划分服务是很常见的,尽管它通常需要一些例外,但它通常可以正常工作。

不过,您编写的 IoC 代码有各种各样的错误。IoC 的目标是将执行依赖项管理的所有代码保存在一个不碍事的地方。您的代码有 CarService 显式实例化 WheelService,而这应该由您的 IoC 容器处理。此外,拥有 GetRepository 方法非常尴尬,并且应该由您的 IoC 容器自动处理。

您可以设置服务和存储库的一种方法是这样的(如果您使用的是构造函数注入)。这只是一个例子(并且是一个冗长的例子),不要在没有完全理解它的情况下将这个结构复制到你自己的代码中。

public interface IRepository {
    //Some interfaces
    //This method could only really be implemented if you are using an ORMapper like NHibernate
    public T FindById<T>(Object id) { }
}

public class BaseRepository : IRepository {
    //Some base crud methods and stuff. You can implement this if you're using an ORMapper
    public T FindById<T>(Object id) 
    { 
        return CurrentSession.FindById<T>(id);
    }
}

public class WheelRepository : BaseRepository {
    //Wheel crud

    //If you don't have an ORMapper because you're a masochist you can implement this here
    public Wheel FindById(Object id) { }
}

public class CarRepository : BaseRepository {
    //Car crud

    //If you don't have an ORMapper because you're a masochist you can implement this here
    public Car FindById(Object id) { }
}

public class BaseService {
    protected BaseRepository _baseRepository;

    //This constructor is automatically called by your IoC container when you want a BaseService
    public BaseService(BaseRepository repository)
    {
        _baseRepository = repository;
    }

    //More methods
}

public class WheelService : BaseService
{
    protected WheelRepository _wheelRepository;

    public WheelService(WheelRepository wheelRepo) : base(wheelRepo)
}

public class CarService : BaseService
{
    protected WheelService _wheelService;
    protected CarRepository _carRepository;

    public CarService(WheelService wheelService, CarRepository carRepository)
    {
        _wheelService = wheelService;
        _carRepository = carRepository;
    }
}

由于您使用的是 MVP,我假设某种 WPF/Winforms 应用程序,但我想如果您真的想让它适合 asp.net,您也可以做一个 Web 应用程序。在任何一种情况下,它们都有一个工厂,您可以配置它来创建您的演示者类。在那个工厂里,你会让它在那里完成所有的注射,在一个你永远不必担心甚至在设置后看的地方不碍事。该代码只会调用它:

//Override the default factory method (just made this up)
public override Presenter GetPresenter(Type presenterType)
{
    return ComponentFactory.GetInstance(presenterType);
}

然后,如果您有一个依赖于服务的演示者,它会自动在那里,服务所需的一切也将在那里。请注意,其他任何地方都没有丑陋的服务构造函数或工厂调用。所有依赖项都由容器自动设置。

我不知道为什么你们公司的代码有那些糟糕的 GetRepository 方法。这是反模式的一个实例,因为您正在用 GetRepository 调用替换通常像 new Repository() 这样的构造函数调用,而这只是稍微更易于维护。

您应该尝试使用一些知名的容器。Structuremap是一个相当不错的。

于 2012-08-10T08:28:47.520 回答