依赖注入和附加功能

时间:2015-07-09 16:32:43

标签: c# dependency-injection inversion-of-control

这是我的一般性问题所以我会把它归结为非常小的东西。我们有一个通用服务接口。

第一部分

public interface IGenericService<T>
{
    void Create(T add);
    void Read();
    void Update(T obj);
    void Delete(T obj);
}

它的实施:

 public class DogService : IGenericService<Dog>
 {
     void Create(Dog add){}
     void Read(){}
     void Update(Dog obj){}
     void Delete(Dog obj){}
 }

还有第二个回购,它有一些独特的附加功能,比如Miau()

 public class CatService: IGenericService<Cat>
 {
     void Create(Cat add){}
     void Read(){}
     void Update(Cat obj){}
     void Delete(Cat obj){}
     void Miau(){}
 }

现在使用一些IOC时我会选择:

Bind<IGenericService<Dog>,DogService>
Bind<IGenericService<Cat>,CatService>

现在在Viewmodel的某个地方:

public class CatsViewModel
{
    public CatsViewModel(IGenericService<Cat> catService)
    {
        //how to have Miau functionality here?
    }
}

1.我如何在这里使用Miau功能?我应该像IDogService一样为DogService创建第二个接口并在这里使用它吗?那么仿制仓库的目的是什么?

第二部分 让我们像这样使用GenericViewModel:

public abstract class GenericViewModel<T>
{
    T Collection { get; }
    public GenericViewModel(IGenericService<T> service)
    {
        Collection = service.Read();
    }
}

这很好。但是,如果我想将它与CatService一起使用

,该怎么办?
public class CatViewModel : GenericViewModel<Cat>
{
    public CatViewModel(IGenericService<T> service) : base(service)
    {
        // make miau here?
    } 
}
  1. 我应该创建ICatService接口并使用两个不同的接口注入相同服务的实例吗?我知道我可以从IGenericService转发它,因为我知道这是什么类型的服务,但这是一个好方法吗?

    这些问题是关于良好的习惯而不是关于解决方案的正常工作:)

1 个答案:

答案 0 :(得分:1)

想到一些选择:

非通用接口

  

那么通用回购的目的是什么?

的确,它的目的是什么?为每个目的键入一个接口有多困难?

public interface IDogService
{
    void Create(Dog add);
    void Read();
    void Update(Dog obj);
    void Delete(Dog obj);
}

public interface ICatService
{
    void Create(Cat add);
    void Read();
    void Update(Cat obj);
    void Delete(Cat obj);
    void Miau();
}

现在,每个使用者都可以请求他们需要的依赖项。 ICatService的客户可以消费Miau

通过额外的行为作为额外的依赖项

另一种选择是保留通用IGenericService<T>,但为Miau功能添加另一项服务:

public interface IMiauService
{
    void Miau();
}

然后让需要IMiauService的客户端通过其构造函数请求它:

public class CatsViewModel
{
    private readonly IGenericService<Cat> catService;
    private readonly IMiauService miauService;

    public CatsViewModel(IGenericService<Cat> catService, IMiauService miauService)
    {
        this.catService = catService;
        this.miauService = miauService;
    }

    // Members can use both services as needed...
}

此解决方案提示了第三个更好的选择:

遵循依赖倒置原则

根据Dependency Inversion Principle,客户端应定义所需的API,然后由具体类来实现该API。

因此,如果类需要 read write 功能,则应通过声明相应的接口来通告该需求:

public interface IReader<T>
{
    T Reader();
}

public interface IWriter<T>
{
    void Write(T item);
}

public class GenericViewModel<T>
{
    private readonly IReader<T> reader;
    private readonly IWriter<T> writer;

    public GenericViewModel(IReader<T> reader, IWriter<T> writer)
    {
        this.reader = reader;
        this.writer = writer;
    }

    // Members can use the reader and writer services...
}

OP IGenericService<T>之类的接口闻起来像是在确定需求之前就已定义的东西,现在您正在尝试将方形钉插入圆孔中。