Dependency Injection Container

帅比萌擦擦* 提交于 2019-12-04 20:44:54

Firstly, the AzureDataProvider has a dependency on the ConfigurationManager. This should be injected in instead.

Secondly, this DataProvider should be injected into the DataAccessConsumer.

This means that a realistic application will have good dependency injection throughout, with no dependency on the container, however you will then need to the "wiring" - connecting all the dependencies together. This is a pain - use the DependencyInjectionContainer only at the main entry point to help resolve this wiring. (This allows you to use a more convenient declarative approach rather than an imperative approach, because you can ask the container "Get me the DataAccessConsumer", and the dependency injection framework will figure out the dependencies for you.

My favorite dependency injection framework for C# is NInject2.

Well, I rolled out my own DI. If the goal is to achieve portability then I think I have come to a semi-acceptable solution. The disadvantages are that you cannot truly achieve a full DI, however in the context of my application it is good enough.

Connection Interface:

public interface IConnection
{
    public string ConnectionString;
}

Concrete Connection Implementation

public class Connection: IConnection
{
    public string ConnectionString{ get; set; }

    public Connection(string connectionString)
    {
        this.ConnectionString = connectionString;
    }

    public Connection():this(ConfigurtionManager.ConnectionStrings["connection"].ConnectionString)
    {
        //Broke DI in the interest of usability.
    }
}

Data Access Layer Interface

public interface IDataProvider
{
    IConnection Connection;

    public void Foo();
}

Concrete Data Access Layer Implementation

public class AzureProvider : IDataProvider
{
    IConnection Connection { get; set; }

    public AzureProvider(IConnection connection)
    {
        this.Connection = connection;
    }

    public void Foo()
    {

    }
}

DI Conainer / Factory (Singleton or Static Class)

public static class ProviderFactory
{
    public static IDataProvider GetProvider()  //I'd pass parameters if I had more than 1.
    {
        Connection connection = new Connection(); //this is why I broke DI.
        IConnection iConnection = (IConnection)connection;

        AzureProvider azureProvider = new AzureProvider(iConnection);
        IDataProvider iDataProvider = (IDataProvider)azureProvider;

        return iDataProvider;
    }
}

Data Access Layer Consumer (in this sample it is a page):

public class SomePage : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        IDataProvider provider = ProviderFactory.GetProvider();
        provider.Foo();
    }
}

As you can see, the page doesn't need to know any of the implementation details of the data access layer. As long as the ProviderFactory can spit IDataProvider, the page is happy. Therefore, if we decide to change providers, say SqlStorageProvider, as long as it implements IDataProvider Interface, the Page's code will not have to be changed. This achieves true separation of concerns in terms of software architecture.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!