Unity for asp.net webapplication with class library

Jul 30, 2012 at 12:47 PM
Edited Jul 30, 2012 at 12:48 PM

I am using Unity in my webapplication project. I also have other library project ex. Presentation, Data. My Unity configuration is in web.config file in main and only one webapplication project.

My problem is I can not use dependency injection from one libary to another. I want to inject property IDataService from library Data in library Presentation in class PlayViewPresenter.

This is section fomr configuration file:

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IDataService" type="Data.IDataService, Data"/>
<alias alias="DataService" type="Data.DataService, Data"/>
<alias alias="PlayViewPresenter" type="Presentation.PlayViewPresenter, Presentation"/>
<assembly name="Data"/>
<assembly name="Presentation"/>
<namespace name="Data"/>
<namespace name="Presentation"/>

<container name="application">
</container>

<container name="session">
<register type="IDataService" mapTo="DataService">
<lifetime type="TransientLifetimeManager"/>
</register>

</container>
</unity>
Unity works fine if use dependency on that propert in webapplication project, but i cano get through that with another libary. Is it possible to inject different library projectc with unity defined in webapplicaiton project in .config file?
Jul 30, 2012 at 4:15 PM
Edited Jul 30, 2012 at 4:18 PM

Yes, you should be able to to inject class library projects in a web application via configuration files.  You just need to ensure that the configuration is set up, that in the web application call LoadConfiguration on the UnityContainer, and ensure that the class library assemblies are resolvable by the container.

Your web.config configuration looks fine although you don't need the aliases since you also have assembly and namespace tags.

Where you set up the container depends on your design but if we assume that every user gets their own container (since your container is called session) then in global.asax you could create a container and save it so it can be accessed when required to resolve objects:

public class Global : System.Web.HttpApplication
    {
        void Application_Start(object sender, EventArgs e)
        {
            IUnityContainer container = new UnityContainer();
            container.LoadConfiguration("session");
            Application["unityContainer"] = container;
        }

        void Session_Start(object sender, EventArgs e)
        {
            var container = Application["unityContainer"] as IUnityContainer;
            Session["unityContainer"] = container.CreateChildContainer();
        }

        void Session_End(object sender, EventArgs e)
        {
            // Code that runs when a session ends. 
            // Note: The Session_End event is raised only when the sessionstate mode
            // is set to InProc in the Web.config file. If session mode is set to StateServer 
            // or SQLServer, the event is not raised.
            var container = Session["unityContainer"] as IUnityContainer;
            container.Dispose();
        }
    }

Then later:

    var container = Session["container"] as IUnityContainer;
    var presenter = container.Resolve<PlayViewPresenter>();

If you are encountering issues, could you provide more details about the exact scenario to reproduce the issue?

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jul 30, 2012 at 4:46 PM

Thanks for reply. This is what I was looking for:

    var container = Session["container"] as IUnityContainer;
    var presenter = container.Resolve<PlayViewPresenter>();

These are lines I was missing. Now everything works fine.

Jul 30, 2012 at 10:30 PM

I have classic presenter class (MVP):

public PlayViewPresenter(IPlayView view) {
            View = view;
        }

 What is the best approach to set view property in presenter with constructor:

 

container.RegisterInstance(typeof(IPlayView), this);
var presenter = container.Resolve<PlayViewPresenter>();

or simply:
var presenter = container.Resolve<PlayViewPresenter>();//presenter without parameters
presenter.View = this;

I am wonderring if 1. is good for performance, to register instance of view.
Jul 31, 2012 at 1:48 AM

Typically, you would not manually assign the View.  Instead you would rely on the container to perform Constructor, Property, or Method injection for you.  Exactly how to do this depends on the chosen design. The article Creating A Generic Model-View-Presenter Framework seems like a good approach.  In that article the BuildUp method (which Unity supports) is used to perform injection on an existing instance.

Another approach is used by http://webformsmvp.codeplex.com/.  That project uses RegisterInstance to register the specific view.

You could also specify a DependencyOverride:

var presenter = container.Resolve<PlayViewPresenter>(
        new DependencyOverride<IPlayView>(new InjectionParameter(this)));
--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Jul 31, 2012 at 9:09 AM

Thanks for full clarification.