8

I am developing a .Net Web Forms project structure and I decided to use Unity as a DI framework for the application.

MSDN-Resolving in Asp.Net states that in order to inject dependencies in my project I need to build up the initial object which is created outside of the DI container. That being said we come to the question.

  1. The attribute annotations such as [Dependency] are classes extending the Attribute class. In order to use them, another namespace must be included in the declaring class, thus making our class dependent on the Microsoft.Practices.Unity.DependencyAttribute class. So now, even though our class might not be aware of the implementation of IMyInterface that it uses, it has to be aware of the concrete implementation of the Dependency class? What is it that I am missing here? If we were to change the DI framework, we would need to remove all the annotations throughout the project.

  2. Is there a way to avoid this kind of declaration (configuration files or what-not) outside of the container?

EDIT --> Code here

/*This is the abstract base class where I want the dependency injection to occur*/
public abstract class BasePage : System.Web.UI.Page 
{
    private IMyService _dtService;   
    public IMyService DtService
    {
        get { return _dtService; }
        set { _dtService = value; }
    }
}

The Default.aspx code behind

public partial class _Default : BasePage
{

    public _Default( )
    {

    }

    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            DataClass dt = DtService.GetDataById(2);
            lblWhatever.Text = dt.Description;
        }
    }
}

Global code behind

public class Global : System.Web.HttpApplication
{
   void Application_Start(object sender, EventArgs e)
    {
        IUnityContainer myContainer = HttpContext.Current.Application.GetDIContainer();
        myContainer.RegisterType<IMyService,MyServiceClient>(new 
                     InjectionConstructor("MyServiceWsEndpoint"));
        // I have tried this with BasePage too
        myContainer.RegisterType<_Default>(new InjectionProperty("DtService"));

    }
}

And the module

public class UnityHttpModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.PreRequestHandlerExecute += OnPreRequestHandlerExecute;
    }

    public void Dispose() { }

    private void OnPreRequestHandlerExecute(object sender, EventArgs e)
    {
        IHttpHandler currentHandler = HttpContext.Current.Handler;
        /*This does not work*/
HttpApplicationStateExtensions.GetDIContainer(HttpContext.Current.Application).BuildUp(
                          currentHandler.GetType(), currentHandler);
        /* While this works*/
HttpApplicationStateExtensions.GetDIContainer(HttpContext.Current.Application).BuildUp<_Default>((_Default)currentHandler);

        var currentPage = HttpContext.Current.Handler as Page;
        if (currentPage != null)
        {
            currentPage.InitComplete += OnPageInitComplete;
        }
    }
}

The code inside the module is reached every time. The line Does INDEED work when I use the [Dependency] Attribute.

Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • 2
    Most IOC containers do not place this kind of constraint on you. If it causes a problem, you might consider an alternative container - eg. structuremap, autofac, simpleinjector etc. – MattDavey Jul 15 '13 at 11:43
  • 1
    It isn't so much a constraint of the Unity Framework, it is more a constraint of the asp.Net WebForms, where I cannot control the Construction of the Objects, so I need do Property injection. Those other DI frameworks can do Property injection without altering the class that needs said injection? – Athanasios Kataras Jul 15 '13 at 12:14
  • 2
    That's right - the first answer to [this question](http://stackoverflow.com/questions/4979453/structuremap-beginner-property-injection) describes exactly that scenario (using Structuremap). I'd assume that the majority of DI libraries include this behaviour. – MattDavey Jul 15 '13 at 12:47

1 Answers1

5

Yes, peppering code with Dependency attributes tightly couples the implementation to the container.

There are a few ways to determine what properties to inject:

  • Attributes
  • XML Configuration
  • Programmatic Configuration
  • Custom container extension

One way to get around the use of attributes is to register all of the pages and specify programmatically what properties to inject and supply overrides as needed to BuildUp:

IUnityContainer container = new UnityContainer();

// Assume we have a logger we are injecting
container.RegisterType<ILogger, Logger>(new ContainerControlledLifetimeManager());

// Register the Dependency Properties for the Page 'MyPage'.
// Property names on MyPage are "Logger"
container.RegisterType<MyPage>(new InjectionProperty("Logger"));

// ...later

IHttpHandler currentHandler = HttpContext.Current.Handler;

// Perform Property Injection.  
// Logger will be injected from the existing container registration.  
container.BuildUp(currentHandler.GetType(), currentHandler);
Randy Levy
  • 22,566
  • 4
  • 68
  • 94