5

Im trying to get Unity to work with my console application, however.. all the properties that I try to dependency inject are still set to null.

This is my code:

Program.cs

namespace .Presentation.Console
{
    class Program
    {
        static void Main(string[] args)
        {
            var mainThread = new MainThread();
        }
    }
}

MainThread.cs

namespace xxxx.Presentation.Console
{
    public class MainThread
    {
        public IUnitOfWork UnitOfWork { get; set; }

        public IMapper Mapper { get; set; }

        public MainThread()
        {
            Mapper.RegisterMappings();
        }
    }
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.1" />
  </startup>
  <unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="IDataAccess" type="UnityFramework.IDataAccess, UnityFramework" />
    <namespace name="UnityFramework" />
    <assembly name="UnityFramework" />
    <container>
      <types>

        <type type="IMapper" mapTo="xxxx.Core.Parse.ParseMapper" />

      </types>
    </container>
  </unity>
</configuration>

App.config is set to Copy Always

Where Mapper is returned as null in this case (and I assume UnitOfWork is as well)

Do I need to do anything else? Add something to the app.config? Am I missing something?

Thanks in advance!

Br, Inx

Inx51
  • 1,911
  • 3
  • 24
  • 44
  • Please, please, please don't use annotations. The container knows about components but *components should never know about the container.* – user2864740 Mar 17 '15 at 15:45
  • In any case the problem is because Unity does not go and 'back fill' properties (much less static ones). It fills in dependencies (ie. *instance* properties, constructor arguments) *when it resolves components*. The top-level (or "root") object/objects in the graph - perhaps the "UoW" here? - are created with manual calls to Resolve. Some integration contexts (eg. WCF/WebAPI/MVC) may already resolve the roots - but a simple program has no such integration context. – user2864740 Mar 17 '15 at 15:52
  • So, your saying that the annotations are not needed? I also changed my code a bit.. could you please have a look and tell me whats wrong.. ill update the post in a few mins. – Inx51 Mar 17 '15 at 15:56
  • They are indeed not needed - and Unity is one of the few IoC containers that even has such! Instead of having the component 'ask' for specific properties to be filled in, have the registration supply that information. (I recommend using standard constructor injection as then no additional work needs to be done.) To get Unity to inject dependencies you *must* create the instance with `container.Resolve` (or have it be automatically resolved as part of a chain).. Unity doesn't do anything for `new`. – user2864740 Mar 17 '15 at 16:38

1 Answers1

12

Unity only supplies dependencies for components obtained via Resolve or while resolving sub-dependencies. The "root" component or components must be obtained from the container manually.

Using new Program would not automatically provide the dependencies because it bypasses the Unity container.

static class ProgramEntry
{
    static void Main(string[] args)
    {
        var unity = CreateUnityContainerAndRegisterComponents();
        // Explicitly Resolve the "root" component or components
        var program = unity.Resolve<Program>();
        program.Run();
    }
}

public class Program
{
    readonly Ix _x;

    // These dependencies will be automatically resolved
    // (and in this case supplied to the constructor)
    public Program(IMapper mapper, Ix x)
    {
        // Use dependencies
        mapper.RegisterMappings();

        // Assign any relevant properties, etc.
        _x = x;
    }

    // Do actual work here
    public void Run() {
        _x.DoStuff();
    }
}

I prefer code-based registration for most tasks.

  • I recommend not using attributes, although they 'will work' if following the Resolve pattern above. The "root" objects must be manually resolved.

    The problem with attributes is these add a dependencies on Unity - so much for "inverting"!

    Constructor Injection (as shown) is automatic/default. See Setter / property injection in Unity without attributes if Property Injection is preferred.

  • I would probably resolve a Factory (or Func<UoW>) to create a UoW and supply it down the call-stack context (ie. pass it to methods) when applicable. The application may have many different UoWs during a single run. In this case you may also be interested in creating scopes.

  • I would also probably use a factory to create a pre-configured IMapper object when it is resolved instead of using RegisterMappings afterwards.

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220