0

I am trying to setup IoC container in my Asp.Net MVC 5 application so I can access these objects anywhere in my application.

I choose to use Unity.Mvc container for the job.

Now, I have a class that looks like this

using Project1.Foundation.Contracts;
using Project2.Respositories.Contracts.UnitsOfWork;
using Unity.Attributes;

namespace Project2.Presenters.Bases
{
    public class BasePresenter
    {
        [Dependency]
        public IUserPassport Passport { get; set; }

        [Dependency]
        public IUnitOfWork UnitOfWork { get; set; }
    }
}

In Project2.dll I added the [Dependency] attribute over both properties that I need to inject as you can see above. But when the application run, both properties are null and not set to an instance.

I also tried to use InjectionProperty instead of having to add [Dependency] like so

container.RegisterType<BasePresenter>(new InjectionProperty("Passport", new ResolvedArrayParameter<IUserPassport>()),
                                      new InjectionProperty("UnitOfWork", new ResolvedArrayParameter<IUnitOfWork>()));  

However, I am still getting the same results, when the class is constructed like so new ChildPresenter() both properties are still null.

Background

Here is how I register the needed types, from a different assembly (Project1.dll), In the UnityConfig class, I have the following method.

public static void RegisterTypes(IUnityContainer container)
{
    container.RegisterType<IUnitOfWork, UnitOfWork>(new ContainerControlledLifetimeManager());
    container.RegisterInstance<IPrincipal>(Thread.CurrentPrincipal);
    container.RegisterType<IUserPassport, UserPassport>(new ContainerControlledLifetimeManager());
}

In another words, I create the IoC in one assembly and I want to use it in a different assembly Not really sure if it matters, I just thought it should be part of the question for celerity.

How can I correctly inject the property using Unity.Mvc IoC container?

Response To comments below

Question from comment below: Why can't I just pass the parameters in the constructor?

If I do that my code will look like this

public class ConsumerController
{
    protected IUserPasspoer Passport { get; set; }
    protected IUnitOfWork UnitOfWork { get; set; }

    public ConsumerController(IUserPasspoer passport, IUnitOfWork unitOfWork)
    {
        Passport = passport;
        UnitOfWork = unitOfWork;
    }

    public ActionResult Index(int? id)
    {
        var presenter = new SomeIndexPresenter();

        return View(presenter);
    }

    public ActionResult Create(int? id)
    {
        var presenter = new ChildPresenter(Passport, UnitOfWork);

        return View(presenter);
    }

    public ActionResult Create(ChildPresenter presenter)
    {
        if(ModelState.IsValid)
        {
            presenter.Save();
            return ReditectToAction("Index");
        }

        return View(presenter);
    }
}

public class BasePresenter
{
    protected IUserPasspoer Passport { get; set; }
    protected IUnitOfWork UnitOfWork { get; set; }

    public ConsumerController(IUserPasspoer passport, IUnitOfWork unitOfWork)
    {
        Passport = passport;
        UnitOfWork = unitOfWork;
    }
}

public class ChildPresenter : BasePresenter
{
    public ConsumerController(IUserPasspoer passport, IUnitOfWork unitOfWork)
      :base (passport, unitOfWork)
    {
    }
}

On the other side, if I can utilize property injection which should be one of the benefits of using Ioc, then I code will look like this

public class ConsumerController : Controller
{
    public ActionResult Index(int? id)
    {
        var presenter = new SomeIndexPresenter();

        return View(presenter);
    }

    public ActionResult Create(int? id)
    {
        var presenter = new ChildPresenter();

        return View(presenter);
    }

    [HttpPost]
    public ActionResult Create(ChildPresenter presenter)
    {
        if(ModelState.IsValid)
        {
            presenter.Save();
            return ReditectToAction("Index");
        }

        return View(presenter);
    }
}

public class BasePresenter
{
    [Dependency]
    protected IUserPasspoer Passport { get; set; }

    [Dependency]
    protected IUnitOfWork UnitOfWork { get; set; }
}

public class ChildPresenter : BasePresenter
{
}
Junior
  • 11,602
  • 27
  • 106
  • 212
  • 2
    Is there a reason you can't just inject them via the constructor like normal? I dont use Unity so I dont really know what benefit this attribute gives you – maccettura Feb 28 '18 at 16:46
  • 1
    Please make sure you are using right `Dependency` attribute (from Unity namespace). Also, in order to inject properties, you have to resolve `PresenterBase` with Unity too, otherwise Unity will not know about them and they will be null. – Alex Sikilinda Feb 28 '18 at 16:51
  • @AlexSikilinda yes I am sure. the namespace is `Unity.Attributes` – Junior Feb 28 '18 at 16:52
  • You get a compile-time error which indicates the wrong usage of the attribute. The error itself is not connected to Unity. Your `PresenterBase` is okay, are there any other [Dependency] attributes in the solution? – Alex Sikilinda Feb 28 '18 at 16:57
  • @AlexSikilinda no. But please check my updated question, the dependency is injected using a different assembly that could be cause the problem. – Junior Feb 28 '18 at 16:58
  • @MikeA your properties are read only. There is no way to inject a value into them. – Nkosi Feb 28 '18 at 17:40
  • 1
    I understand that this class is a base class for others, so you don't want to have to have all the child classes add these parameters to their constructors. But you should rethink that: if the object has a dependency on something in order to function, it makes sense to require it as part of the constructor. While each child class will need additional logic to pass the dependencies to the base, that shouldn't be too much work. – mason Feb 28 '18 at 18:05
  • Why is `CunsumerController ` creating an instance of `ChildPresenter`? Why isn't that being injected? And did you know you spelled `Consumer` wrong? – mason Feb 28 '18 at 18:30
  • Sorry, that is a typo, I just wrote that example is Sublime :) The HttpPost method will inject the `ChildPresenter` I can't have 2 methods with the same signatures in the same class. First method, renders a form, the second method, process the update. I updated my sample code to express the logic better – Junior Feb 28 '18 at 18:39
  • What is ChildPresenter supposed to be? A ViewModel? Or a service that does some processing? – mason Feb 28 '18 at 18:48
  • @mason it is a class that allow me to wrap my business logic so I can reuse it and thin my controller. It allows me to clear things like `IEnumberable` for the viewModel. it also contains my ViewModel. – Junior Feb 28 '18 at 18:51
  • Sounds like it's doing much much more than it should be doing. You should follow the [Single Responsibility Principle](https://en.wikipedia.org/wiki/Single_responsibility_principle). – mason Feb 28 '18 at 18:53
  • Well it does more than one thing. But it is a service that allows me to encapsulate multiple functions that do one complete service instead of adding lots of logic into my controller. I updated my question yet again to give you an example of how I would implement my presenter. – Junior Feb 28 '18 at 19:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/165990/discussion-between-mike-a-and-mason). – Junior Feb 28 '18 at 19:17
  • 1
    [Using inheritance for a controller is rarely a good idea](https://stackoverflow.com/a/6119341) as it is the tightest form of coupling. It is a *code smell* indicating you should take a step back and analyze further. If you have a [crosscutting concern](https://msdn.microsoft.com/en-us/library/ee658105.aspx), you should use a [filter](https://msdn.microsoft.com/en-us/library/gg416513(VS.98).aspx) to implement it which can be registered globally and optionally controlled by attributes. Injecting the same service into all of your controllers can then be avoided. – NightOwl888 Feb 28 '18 at 19:17
  • I am a bit confused about your recommendation here. What do you suggest I convert my code to? eliminate my `ChildPresenter` class altogether and put that logic into the controller directly? then maybe move the `IEnumerable` into the ViewModel? – Junior Feb 28 '18 at 19:46

1 Answers1

0

If you new the ChildPresenter, Unity isn't involved and won't inject anything.

You have to inject yourself with properties as with constructor parameters, then:

public ActionResult Create(int? id)
{
    var presenter = new ChildPresenter()
        {
            Passport = Passport,
            UnitOfWork = UnitOfWork
        };

    return View(presenter);
}

In my opinion the constructor parameter variant looks nicer...

Haukinger
  • 10,420
  • 2
  • 15
  • 28