0

I have a class with a DAL dependency:

public class FirstClass()
{
    [Dependency]
    public IDalType Dal { get; set; }
}

I can create an instance of the class with:

UnityContainer c = new UnityContainer();  
c.RegisterType<IDalType, DalType>();
FirstClass fc = c.Resolve<FirstClass>();

This will set the dependency and I can use the instance. This is something like a starting main class (main form, main ViewModel).

Now, I have a SecondClass again with a DAL dependency and that second class must be instantiated and called from the first class. How do I do that?

public class FirstClass()
{
    [Dependency]
    public IDalType Dal { get; set; }

    public DoSomething()
    {
        ??? SecondClass sc = App.UnityContainer.Resolve<SecondClass>();
    }
}

If I use the UnityContainer inside the first class, that will be a coupling with the container, and I will have to map IDAL -> DAL somewhere in application root and have a static container.

I read that coupling with the container is bad, as well as using static map: http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx

net_prog
  • 9,921
  • 16
  • 55
  • 70

2 Answers2

1

Add SecondClass as a dependency of FirstClass:

public class FirstClass
{
    [Dependency]
    public IDalType Dal { get; set; }

    [Dependency]
    public SecondClass Sc { get; set; }

    public DoSomething()
    {
        sc.DoWhatever();
    }
}

However, I'd strongly recommend switching to constructor injection instead:

public class FirstClass
{
    private IDalType dal;
    private SecondClass sc;

    public FirstClass(IDalType dal, SecondClass sc) 
    {
        this.dal = dal;
        this.sc = sc;
    }

    public DoSomething()
    {
        sc.DoWhatever();
    }
}

This way you aren't coupled to the container via the attributes, and you aren't exposing properties that are only there as inputs (confusing your class's public interface), and you guarantee you can't create an instance of FirstClass without it having all the dependencies it needs.

UPDATE

If you need to create the instance on demand, you can instead inject Func. Unity will create a factory method for you that, when invoked, will call back into the container.

public class FirstClass
{
    private IDalType dal;
    private Func<SecondClass> scFactory;

    public FirstClass(IDalType dal, Func<SecondClass> scFactory) 
    {
        this.dal = dal;
        this.scFactory = scFactory;
    }

    public DoSomething()
    {
        SecondClass cs = scFactory();
        sc.DoWhatever();
    }
}

If you have more complex requirements to choose which helper object does what, I'd reevaluate if you should be getting the object in question from the container at all. Instead, consider injecting an explicit factory object instead.

Chris Tavares
  • 29,165
  • 4
  • 46
  • 63
  • And what if the instance of the SecondClass is required on demand, let's say, conditionally - SecondClass if something1 or ThirdClass if something2 - the instance must be created inside a method of the FirstClass. – net_prog Jun 11 '12 at 17:54
  • @Chris - The automatic factory method creation looks interesting. Do you have a link to the Unity docs that describes this more? Also I think your update code has a typo. Your constructor is still taking an SecondClass as input. scFactory is never initialized. – ErnieL Jun 11 '12 at 22:06
1

Using a factory will put some knowledge about the instantiation of a service (your SecondClass) inside your consumer. In this post Mark Seemann describes another approach.

And if you don't want to waste time and effort coding those type of adapters have a look at the TecX project on CodePlex. It adds support for generating lazy proxies on-the-fly using Unity.

Community
  • 1
  • 1
Sebastian Weber
  • 6,766
  • 2
  • 30
  • 49