IOC Between Presentation and Infrastructure Layer – C# Guide

cdependency-injectiondesign-patternsinversion-of-control

Question:
I would like to set forth dependency mapping from a *.config file from a project that has no reference to the project that contains the concrete class.

Scenario:
I'll be using terms from C#, Microsoft Unity and Visual Studio: I've got a presentation layer with a web service project and a winform project, an infrastructure layer that communicates with repositories, and there is a core business logic layer that defines interfaces that the infrastructure must implement.

Projects:
Presentation:
DIApplication.WebServices – references the Core + DependencyResolution projects
DIApplication.Winform – references the Core + DependencyResolution projects

Infrastructure:
DIApplication.Data – Communicates with repositories, references the Core
DIApplication.DependencyResolution – Registers to the dependencies from Core to Data projects. These are the only two projects it references

Core:
DIApplication.Core – Defines interfaces, references nothing

Example:
For an example I'll say I have DIApplication.Core.IRepository interface and DIApplication.Data.RepositoryA class and DIApplication.Data.RepositoryB class.

It's fine to say that the DependencyResolution project will register the dependencies:

//If Application == WebService
container.RegisterType<IRepository , RepositoryA >();
//Else
container.RegisterType<IRepository , RepositoryB >();

But what I would like to do is that the Webservices Web.config maps IRepository to RepositoryA, while the Winforms App.config maps IRepository to RepositoryB

Webservices:

< register type="DIApplication.Core.IRepository, DIApplication.Core" mapTo=" DIApplication.Data.RepositoryA, DIApplication.Data" />

Winforms:

< register type="DIApplication.Core.IRepository, DIApplication.Core" mapTo=" DIApplication.Data.RepositoryB, DIApplication.Data" />

The problem (I believe) is that neither DIapplication.Webservices or Winforms knows about DIapplication.Data, so it breaks on the final portion of this call in DIApplication.DependencyResolution:

IUnityContainer container = new UnityContainer();
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(container);

With the error:

The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047) 

Is there any way to get around this without having to include a reference to DIApplication.Data within both DIApplication.Webservices and Winforms?

Maybe I'm looking at this the wrong way. I know that it kind of breaks the notion of separation of concern, where the presentation layer shouldn't know nor care how data is being persisted to repositories, just that it is. But I also want to drive the dependencies based on what project is running.

Best Answer

The context of your application decides everything.

To illustrate why this is true, let us first start with the purpose for inversion of control or IOC. The purposes behind IOC are extensibility and horizontal scaling.

In extensibility, the application needs to decide what implementation to use under a particular set of circumstances. For example, if the user chooses to pay via PayPal, it needs to choose the PayPalPaymentProvider implementation rather than the Authorize.NET implementation.

For horizontal scaling, the implementation is decoupled from the application code so that you can easily scale up by writing new implementations and setting those within the context of your application. For example, if my application currently uses MySql, but I'm now to the point where MySql isn't performing well because my application has become too popular, using IOC I can simply write a new database implementation that is SQL specific and throw out the MySql code without having to change any application logic at all.

All of that being said, let's add the fact the presentation layer is nearly always tied to a specific environment that it needs to run under. Unless you either write your own application host or OS or you abstract your entire UI into its own project that is then hosted by a context project, the project that contains your UI IS going to be the decision maker for everything implementation related.

Now, to answer your question. You do not need to have a reference to the DIApplication.Data project in your DIApplication.Webservices or DIApplication.Winforms projects and you don't want to reference it directly because then it defeats the purpose of using the IOC. However, you will need to copy the dll for DIApplication.Data into the context of your applications so that it can read the assembly. Defining what implementation you want to use for the IOC in the web.config and app.config is good practice.

However, for the IOC to be able to read and instantiate the concrete implementation, it must be able to find it. The idea here is that you could swap out that dll with a different concrete implementation, change the configuration file to point to the new concrete instance and everything would continue to work without needing to rebuild the application at all, much less having to change any code.

So, to summarize the answer, all you should really need to do at this point is use a post-build action to copy the concrete implementation into the bin folders for your Windows Forms and Web applications.