在需要时从接口转换为具体 class 是一种好习惯吗?

Its is a good practice to cast from an interface to some concrete class when needed?

我正在开发一个小系统,我开发了经典的通用存储库。现在,我的 DAL 有以下架构。

public interface IRepositorio<T> where T : class
{
    T Get(long id);
    long Insert(T obj);
    bool Update(T obj);
    bool Delete(T obj);
}

public abstract class Repositorio<T> : IRepositorio<T> where T : class
{
    public IDbConnection Connection
    {
        get
        {
            return new SqlConnection(ConfigurationManager.ConnectionStrings["DBFila"].ConnectionString);
        }
    }

    public T Get(long id)
    {
        //...
    }

    public long Insert(T obj)
    {
        //...
    }

    public bool Update(T obj)
    {
        //...
    }

    public bool Delete(T obj)
    {
        //...
    }
}

我的具体存储库如下所示:

public class FilaRepositorio : Repositorio<FilaRepositorio>
{
    public FilaRepositorio() 
    {
    }

    public void SomeCustomMethod()
    {
        // Some custom method
    }
}

我也在使用 Simple Injector 来遵循 IoC 和 DI 模式,因此,当我尝试调用 "SomeCustomMethod()" 时,我无法访问它(很明显)。看:

public class Processador
{
    private IRepositorio<FilaModel> _repoFila;
    public Processador(IRepositorio<FilaModel> repoFila)
    {
        _repoFila = repoFila;
    }

    public void Processar()
    {
        _repoFila.SomeCustomMethod(); // <-- wrong

        ((FilaRepositorio)_repoFila).SomeCustomMethod();// <-- works
    }
}

鉴于此我有一些问题:

有几个选项可用。进行演员表的主要问题是它是一个实现问题。

如果注入的对象不是 FilaRepositorio 会发生什么?

通过进行转换,您将 class 紧密耦合到不保证是注入依赖项的实现问题。因此,构造函数对于执行其功能所需的内容并不完全真实。

这说明需要练习Explicit Dependencies Principle

The Explicit Dependencies Principle states:

Methods and classes should explicitly require (typically through method parameters or constructor parameters) any collaborating objects they need in order to function correctly.

避免这种情况的一种方法是制作一个派生接口,明确公开其依赖项的所需功能。

public interface IFilaRepositorio : IRepositorio<FilaModel> {
    void SomeCustomMethod();
}

public class FilaRepositorio : Repositorio<FilaModel>, IFilaRepositorio {
    public void SomeCustomMethod() {
        //...other code removed for brevity.
    }
}

并让 Processador 依赖于更有针对性的抽象。

现在根本不需要强制转换,class 明确表达了它的需要。

public class Processador {
    private readonly IFilaRepositorio _repoFila;

    public Processador(IFilaRepositorio  repoFila) {
        _repoFila = repoFila;
    }

    public void Processar() {
        _repoFila.SomeCustomMethod(); // <-- works
    }
}

如果您需要从应用程序的任何部分访问特定方法,那么该特定方法必须是您抽象的一部分,否则无法保证您在更改具体内容时可以使用它class.

我认为您使用转换根本不是一个好主意,在这种情况下通常要做的是创建一个特定的接口来定义您可能需要使用的任何其他方法:

public interface IFilaRepositorio : IRepositorio<Fila>
{
     void SomeCustomMethod();
}

然后在您认为需要使用的代码的任何部分使用和声明该特定接口:

public class Processador
{
    private IFilaRepositorio _repoFila;
    public Processador(IFilaRepositorio  repoFila)
    {
        _repoFila = repoFila;
    }

    public void Processar()
    {
        _repoFila.SomeCustomMethod();
    }
}