Reputation: 2366
I'm unsure of how to fix my current situation. I'm attempting to create a task:
public class whatever
{
[Dependency]
public IReportingBL ReportingBL { get; set; }
private whatever()
{
...task factory creation, etc.
}
private readonly static Lazy<whatever> _instance = new Lazy<whatever>(() => new whatever());
public static whatever Instance { get { return _instance.Value; }
public Task GetStuff()
{
return _taskFactory.StartNew(() =>
{
return ReportingBL.Method1;
});
}
}
ReportingBL doesn't get resolved. If I create a new instance of ReportingBL inside the thread then the layers below it don't get resolved.
How do I go about getting unity to work in this situation?
Upvotes: 1
Views: 1424
Reputation: 172666
You are applying the Singleton Design Pattern. This is a pattern that is frown upon and considered an anti-pattern by some. In Dependency Injection terminology the Singleton pattern can be considered an Ambient Context, which is a pattern that should hardly ever be used in the context of Dependency Injection.
The Singleton Design Pattern does not work well with Dependency Injection, because:
Instance
field, causes the consumers to violate the Dependency Inversion Principle and disallows the instance from being replaced, mocked, decorated or intercepted. This hinders maintainability and testability of your application.Further more, in your code I don't see any calls to the Unity DI framework. Please remember that a DI container is not a magical tool that will allow classes to be initialized 'by them selves'. In your code you new up whatever
directly; Unity is not involved in this. Unity (or any DI library for that matter) can only auto-wire the object if it is in control of it. In other words, you will have to call container.Resolve<whatever>()
for Unity to build up your instance.
Although you could call container.Resoolve
from within the Lazy<T>
factory delegate, this forces the class to take a dependency on the container itself, which is commonly referred to as the Service Locator anti-pattern.
Instead, I propose the following changes to your design:
This results in the following code:
public interface IWhatever
{
Task GetStuff();
}
public class Whatever : IWhatever
{
private readonly IReportingBL reportingBL;
public whatever(IReportingBL reportingBL) {
this.reportingBL = reportingBL;
}
public Task GetStuff() {
return _taskFactory.StartNew(() => {
return ReportingBL.Method1;
});
}
}
// Some consumer of whatever
public class MyController : Controller
{
private readonly IWhatever whatever;
public MyController(IWhatever whatever) {
this.whatever = whatever;
}
public ActionResult Index() {
return View(this.whatever.GetStuff());
}
}
In your composition root, you can configure the class as follows:
var container = new UnityContainer();
container.RegisterType<IReportingBL, ReportingBL>(
new ContainerControlledLifetimeManager());
container.RegisterType<IWhatever, Whatever>(
new ContainerControlledLifetimeManager());
var controller = container.Resolve<MyController>();
controller.Index();
Upvotes: 2