依赖注入和附加功能

本文关键字:功能 注入 依赖 | 更新日期: 2023-09-27 18:01:58

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

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){}
 }

第二个repo有一些独特的附加功能,比如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功能?我是否应该为DogService创建第二个接口,比如IDogService,然后在这里这样使用它?那么通用回购的目的是什么呢?

让我们像这样设置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?
    } 
}
  • 我是否应该创建ICatService接口并使用两个不同的接口注入相同服务的实例?我知道我可以从genericservice转换它,因为我知道这是什么类型的服务,但这是一个好方法吗?

    这些问题是关于良好习惯的,而不是关于解决方案的。

  • 依赖注入和附加功能

    我想到了几个选项:

    <标题> 非泛型接口

    通用回购的目的是什么?

    的确,它的目的是什么?为每种用途输入一个界面有多难?

    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...
    }
    

    这个解决方案暗示了第三个更好的选择:

    遵循依赖倒置原则

    根据依赖倒置原则,客户端应该定义他们需要的API,然后由具体的类来实现该API。

    因此,如果一个类需要readwrite功能,它应该通过声明相应的接口来宣布这种需求:
    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>这样的接口闻起来就像在需求被确定之前已经定义的东西,现在你正试图将方头钉入圆孔。