interface and cannot be constructed on Unity config - c#

I have trouble to use Unity on this project.
The error is
The current type, Business.Interfaces.IPersonnelBusiness, is an
interface and cannot be constructed. Are you missing a type mapping?
I've updated the Unity to thge latest version because of stackoverflow issueand I saw that RegisterComponents has changed to lazy loaded one
here is the Global asax:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Unity settings
//UnityConfig.RegisterComponents();
// For logging
//SetupSemanticLoggingApplicationBlock();
}
Here is the UnityConfig file:
public static class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Configured Unity Container.
/// </summary>
public static IUnityContainer Container
{
get
{
return container.Value;
}
}
#endregion
/// <summary>
/// Registers the type mappings with the Unity container.
/// </summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>
/// There is no need to register concrete types such as controllers or
/// API controllers (unless you want to change the defaults), as Unity
/// allows resolving a concrete type even if it was not previously
/// registered.
/// </remarks>
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below.
// Make sure to add a Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your type's mappings here.
// container.RegisterType<IProductRepository, ProductRepository>();
container = new UnityContainer();
// Identity managment
container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager());
container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<PersonnelController>(new InjectionConstructor());
container.RegisterType<UsersAdminController>(new InjectionConstructor());
// Business Layer
container.RegisterType<ILogBusiness, LogBusiness>();
container.RegisterType<IAnomalyBusiness, AnomalyBusiness>();
container.RegisterType<ICockpitStatBusiness, CockpitStatsBusiness>();
container.RegisterType<IDocumentBusiness, DocumentBusiness>();
container.RegisterType<IEmailBusiness, EmailBusiness>();
container.RegisterType<IMessageBusiness, MessageBusiness>();
container.RegisterType<INatureBusiness, NatureBusiness>();
container.RegisterType<IPersonnelBusiness, PersonnelBusiness>();
container.RegisterType<ISAPBusiness, SAPBusiness>();
// Set resolver
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
Thanks folks
EDIT:
here is the stack and the code where it is thrown:
StackTrace:
[ResolutionFailedException: Resolution of the dependency failed, type = 'APPI.WEB.Controllers.HomeController', name = '(none)'.
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The current type, APPI.Business.Interfaces.IPersonnelBusiness, is an interface and cannot be constructed. Are you missing a type mapping?
-----------------------------------------------
At the time of the exception, the container was:
Resolving APPI.WEB.Controllers.HomeController,(none)
Resolving parameter 'personnelRepo' of constructor APPI.WEB.Controllers.HomeController(APPI.Business.Interfaces.IPersonnelBusiness personnelRepo, APPI.Business.Interfaces.IAnomalyBusiness anomalyRepo, APPI.Business.Interfaces.IDocumentBusiness docRepo, APPI.Business.Interfaces.IMessageBusiness msgRepo, APPI.Business.Interfaces.ICockpitStatBusiness cockpitStatRepo, APPI.Business.Interfaces.INatureBusiness natureRepo)
Resolving APPI.Business.Interfaces.IPersonnelBusiness,(none)
]
Controller:
public class HomeController : BaseController
{
private readonly IPersonnelBusiness _IPersonnelBusinessRepo;
private readonly IAnomalyBusiness _IAnomalyBusinessRepo;
private readonly IDocumentBusiness _IDocumentBusinessRepo;
private readonly IMessageBusiness _IMessageBusinessRepo;
private readonly ICockpitStatBusiness _ICockpitStatBusinessRepo;
private readonly INatureBusiness _INatureBusinessRepo;
// Unity inject references
public HomeController(IPersonnelBusiness personnelRepo, IAnomalyBusiness anomalyRepo, IDocumentBusiness docRepo,
IMessageBusiness msgRepo, ICockpitStatBusiness cockpitStatRepo, INatureBusiness natureRepo)
{
_IPersonnelBusinessRepo = personnelRepo;
_IAnomalyBusinessRepo = anomalyRepo;
_IDocumentBusinessRepo = docRepo;
_IMessageBusinessRepo = msgRepo;
_ICockpitStatBusinessRepo = cockpitStatRepo;
_INatureBusinessRepo = natureRepo;
}
public HomeController()
{
}
public ActionResult Index()
{
return RedirectToActionPermanent("Cockpit", "Home");
}
There is also the UnityActivator that is called before starting app thanks to
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(APPI.WEB.UnityMvcActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(APPI.WEB.UnityMvcActivator), "Shutdown")]
UnityActivator:
public static class UnityMvcActivator
{
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start()
{
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>
/// Disposes the Unity container when the application is shut down.
/// </summary>
public static void Shutdown()
{
UnityConfig.Container.Dispose();
}
}

As pointed out in the comments, the issue is that you are instantiating 2 different containers, once in your initializer:
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer(); // <-- new container here
RegisterTypes(container);
return container;
});
And once in your RegisterTypes method:
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below.
// Make sure to add a Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your type's mappings here.
// container.RegisterType<IProductRepository, ProductRepository>();
container = new UnityContainer(); // <-- new container here
...
The type mappings are added in the RegisterTypes method to a different instance than the container you are passing in as an argument.
To make it work right, you should remove the instantiation of the container in RegisterTypes so it can use the instance that is passed in the parameter.
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below.
// Make sure to add a Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your type's mappings here.
// container.RegisterType<IProductRepository, ProductRepository>();
// container = new UnityContainer(); // <-- Remove this
...

Related

Dependency injection integration with Unity.MVC, container.Resolve cannot be used with arguments of type

I'm trying to integrate Dependency Injection with Unity.MVC to my project. With the default configuration that Unity has, controllers works perfectly fine but I would like to implement DI en other classes...
This is the configuration I use:
I added this line on global.asax UnityMvcActivator.Start();
public static class UnityMvcActivator
{
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start()
{
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>
/// Disposes the Unity container when the application is shut down.
/// </summary>
public static void Shutdown()
{
UnityConfig.Container.Dispose();
}
}
The last one comes by default and works perfectly with the controllers
public static class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Configured Unity Container.
/// </summary>
public static IUnityContainer Container => container.Value;
#endregion
/// <summary>
/// Registers the type mappings with the Unity container.
/// </summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>
/// There is no need to register concrete types such as controllers or
/// API controllers (unless you want to change the defaults), as Unity
/// allows resolving a concrete type even if it was not previously
/// registered.
/// </remarks>
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below.
// Make sure to add a Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your type's mappings here.
// container.RegisterType<IProductRepository, ProductRepository>();
if (Global.BOT_CONECTADO)
{
container.RegisterSingleton<ISeguidorRepository, DBSeguidorRepository>();
container.RegisterSingleton<IActivoRepository, DBActivoRepository>();
container.RegisterSingleton<ICategoriaRepository, DBCategoriaRepository>();
container.RegisterSingleton<IJuegoSecundarioRepository, DBJuegoSecundarioRepository>();
container.RegisterSingleton<ISaludosRepository, DBSaludosRepository>();
}
else
{
container.RegisterSingleton<ISeguidorRepository, FakeSeguidorRepository>();
container.RegisterSingleton<IActivoRepository, FakeActivoRepository>();
container.RegisterSingleton<ICategoriaRepository, FakeCategoriaRepository>();
container.RegisterSingleton<IJuegoSecundarioRepository, FakeJuegoSecundarioRepository>();
container.RegisterSingleton<ISaludosRepository, FakeSaludosRepository>();
}
//DependencyResolver.SetResolver(new IDConfigurador(container));
}
}
In the last one I added my registers, but When I try to use them on other contructors, those that are not controllers, they don't work. Looking for answers on google I found this solution that could help me:
container.Resolve()
I tried to use it but I get the following error ==> "The method 'IUnityContainer.Resolve(Type, string, params ResolverOverride[])' non generic cannot be used with arguments of type"
// CONSTRUCTOR
public RepositorioEncuesta()
{
// Error línea de abajo: El método 'IUnityContainer.Resolve(Type, string, params ResolverOverride[])' no
// genérico no se puede usar con argumentos de tipo
_activos = UnityConfig.Container.Resolve<IActivoRepository>();
_seguidores = new DBSeguidorRepository();
_juegos = new DBJuegoSecundarioRepository();
}
How could I use my DI integration to use it on other constructors? Why the Resolve method is not working?
PD: I also tried using a generic, but does not work either.
var activos = UnityConfig.Container.Resolve<IActivoRepository>();

Web API ContainerControlledLifetimeManager - not what expected

I have an ASP.NET MVC application, which serving http pages and provides REST API using Web API.
I have a "service" class, which supposed to be a singleton and to be used both in ASP.NET MVC and Web API parts.
For dependency injection, I using Unity. I installed from NuGet Unity, Unity.AspNet.Mvc and Unity.AspNet.WebApi packages.
I registering my service as singleton:
container.RegisterType<IService, ServiceImp>(new ContainerControlledLifetimeManager());
What I see is that different instances of "ServiceImp" created for ASP.NET MVC and for Web API. The constructor called twice. It looks like there are two separate containers there...
All contents of UnityConfig.cs, UnityMvcActivator.cs and UnityWebApiActivator.cs remained unchanged as initial template, except the place where I register my services.
Any idea how to solve this issue? What I doing wrong?
UnityConfig.cs
namespace Management.App_Start
{
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IService, ServiceImp>(new ContainerControlledLifetimeManager());
}
}
}
UnityMvcActivator.cs
using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Management.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Management.App_Start.UnityWebActivator), "Shutdown")]
namespace Management.App_Start
{
/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
UnityWebApiActivator.cs
using System.Web.Http;
using Microsoft.Practices.Unity.WebApi;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Management.App_Start.UnityWebApiActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Management.App_Start.UnityWebApiActivator), "Shutdown")]
namespace Management.App_Start
{
/// <summary>Provides the bootstrapping for integrating Unity with WebApi when it is hosted in ASP.NET</summary>
public static class UnityWebApiActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
// Use UnityHierarchicalDependencyResolver if you want to use a new child container for each IHttpController resolution.
// var resolver = new UnityHierarchicalDependencyResolver(UnityConfig.GetConfiguredContainer());
var resolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
GlobalConfiguration.Configuration.DependencyResolver = resolver;
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
var container = UnityConfig.GetConfiguredContainer();
container.Dispose();
}
}
}
UPDATE 9.9.17
After some digging, I see that Application_Start called twice - first time when any http page requested and second time when REST API called. As a result, everything initialized twice, including Unity. Now I need to find out why this happens...

Unity LifeTime manager for Quartz.net

I'm trying to use Quartz.Net in a asp.NET MVC application. I'm using Unity as DI, with PerRequestLifeTimeManager.
Quartz.Net, however, doesn't work with PerRequestLifeTimeManager because, well, it doesn't have a request to begin with. Any dependency I try to resolve with it returns null.
I've created a class like an adapter to use two life time managers depending on the context as following:
class CustomLifetimeManager : LifetimeManager
{
private readonly string _key = "CustomLifetimeManagerKey" + Guid.NewGuid();
private readonly PerResolveLifetimeManager _perResolveLifetimeManager = new PerResolveLifetimeManager();
private bool IsWebContext => HttpContext.Current != null;
public override object GetValue()
{
return IsWebContext
? HttpContext.Current.Items[_key]
: _perResolveLifetimeManager.GetValue();
}
public override void SetValue(object newValue)
{
if (IsWebContext)
HttpContext.Current.Items[_key] = newValue;
else
_perResolveLifetimeManager.SetValue(newValue);
}
public override void RemoveValue()
{
if (IsWebContext)
HttpContext.Current.Items[_key] = null;
else
_perResolveLifetimeManager.RemoveValue();
}
}
I've tried PerThreadLifetimeManager, it executes fine for the first time, then the subsequent executions fails with the message
The operation cannot be completed because the DbContext has been
disposed.
I've tried changing to PerResolveLifeTimeManager, but it fails with
An entity object cannot be referenced by multiple instances of
IEntityChangeTracker
My job is pretty straightforward, similar to the following:
[DisallowConcurrentExecution]
class MyJob
{
IFooRepository _fooRepository;
IBarRepository _barRepository;
public MyJob(IFooRepository fooRepository, IBarRepository barRepository)
{
_fooRepository = fooRepository;
_barRepository = barRepository;
}
public void Execute(IJobExecutionContext context)
{
var foos = _fooRepository.Where(x => !x.Processed);
foreach(var foo in foos)
{
var bar = _barRepository.Where(x => x.Baz == foo.Baz);
foo.DoMagic(bar);
foo.Processed = true;
_fooRepository.Save(foo);
}
}
}
And my job factory is
public class UnityJobFactory : IJobFactory
{
private readonly IUnityContainer _container;
public UnityJobFactory(IUnityContainer container)
{
_container = container;
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
return (IJob)_container.Resolve(bundle.JobDetail.JobType);
}
public void ReturnJob(IJob job)
{
}
}
How do I correctly manage dependency life time in a Quartz job?
I had the same issue with Castle.Windsor and Quartz.Net. The only applicable way i found was a ScopedLifetime, but you have to control the Scope by yourself. If a new Request comes in, open a scope and all service will be resolved in this scope (the so called UnitOfWork ;)) and when the request ends, close it.
The job handling is a little bit more trickier. But you have two ways to solve that. For both ways you need a Factory that can start scopes.
Your Job gets a Factory in the constructor and in Execute(IJobExecutionContext context) the factory starts a scope, resolves your service (repositories...) executes whatever the job does and closes the scope. A using(Factory.BeginScope()) works great for this. the downside of this is, it is considered as bad practice because of using the service locator pattern.
public class MyJob
{
private readonly Factory Factory;
public MyJob(Factory factory)
{
Factory = factory;
}
public void Execute(IJobExecutionContext context)
{
using (Factory.BeginScope())
{
var repo = Factory.Create<IFooRepository>();
// Do stuff
Factory.Release(repo);
}
}
}
Your Job gets a Factory or something that can start a scope and your service as function like: Func<IFooRepository> repositoryFunc. Then in your Execute method, start the scope (again with a using) and invoke your repository, it will return your real repository in that scope and you can work with it like you want. This should be the best way. Please note, that this is not considered as Service Locator Pattern, because you give your job the Func<> for the service and you just control the scope.
public class MyJob
{
private readonly Factory Factory;
private readonly Func<IFooRepository> RepositoryFunc;
public MyJob(Factory factory, Func<IFooRepository> repositoryFunc)
{
Factory = factory;
RepositoryFunc= repositoryFunc;
}
public void Execute(IJobExecutionContext context)
{
using (Factory.BeginScope())
{
var repo = RepositoryFunc();
// Do Stuff
}
}
}
The Problem
PerThreadLifetimeManager
The operation cannot be completed because the DbContext has been disposed.
This comes because Quartz uses a MainThread and per default a ThreadPool with 10 Threads. All Jobs are created in the MainThread and then executed in a free thread from the pool. If you start a job, the DBContext is bound to the MainThread. When you start another job, then there is already a DBContext bound to this Thread, no matter if it is disposed or closed and the LifeTimeManager will resolve this already used context. If you start your Job the first time, the Thread is new and you current DBContext is bound to this Thread. When you start the next job and it executes in the same Thread, then there was always a DBContext bound to this Thread. The LifeTimeManager resolves this allready used context, but you can't use it, because its closed.
PerResolveLifeTimeManager
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
This issue comes from EF. Each service that you resolve gets an new Scope, even if you resolve different services with the same constructor. This results in that every Repository you use, have its own DBContext. And EF forbids to use different DBContexts with the same entity.
Got this to work long time ago with simpleinjector.
This was with an older version of Quartz though, hope it can still help
You need to create a custom LifetimeScope
public class LifetimeScopeJobDecorator : IJob
{
private readonly IJob _decoratee;
private readonly Container _container;
public LifetimeScopeJobDecorator(IJob decoratee, Container container)
{
_decoratee = decoratee;
_container = container;
}
public void Execute(IJobExecutionContext context)
{
using (_container.BeginLifetimeScope())
{
_decoratee.Execute(context);
}
}
}
That you call into your job factory
public class SimpleInjectorJobFactory : IJobFactory
{
private readonly Container _container;
public SimpleInjectorJobFactory(Container container)
{
_container = container;
_container.Verify();
}
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
IJobDetail jobDetail = bundle.JobDetail;
Type jobType = jobDetail.JobType;
var job = (IJob)_container.GetInstance(jobType);
return new LifetimeScopeJobDecorator(job, _container);
}
public void ReturnJob(IJob job)
{
}
}
Then you can initialize your custom Quartz Container
public static class QuartzScheduler
{
private static Container _quartzContainer { get; set; }
private static void Initialize()
{
Container container = new Container();
container.RegisterLifetimeScope<IUnitOfWork, SqlUnitOfWork>();
container.Register<ILogger, NLogLogger>();
//To enable lifetime scoping, please make sure the EnableLifetimeScoping extension method is called during the configuration of the container.
container.EnableLifetimeScoping();
container.Verify();
_quartzContainer = new Container();
var schedulerFactory = new StdSchedulerFactory();
_quartzContainer.RegisterSingle<IJobFactory>(() => new SimpleInjectorJobFactory(container));
_quartzContainer.RegisterSingle<ISchedulerFactory>(schedulerFactory);
_quartzContainer.Register<IScheduler>(() =>
{
var scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = _quartzContainer.GetInstance<IJobFactory>();
return scheduler;
}
);
_quartzContainer.Verify();
Start the scheduler
public static void StartJobs()
{
Initialize();
//Ask the scheduler factory for a scheduler
IScheduler scheduler = _quartzContainer.GetInstance<IScheduler>();
scheduler.Start();
}
Please take a look at Quartz.Unity nuget package https://github.com/hbiarge/Quartz.Unity, this unity package has a decent implementation of ScopedLifetime.
In addition to the above nuget package, if you use multiple unity container instances and pass the lifetimemanager as a delegate, it will allow you to properly handle the disposable types such as DBContext for each quartz job as well as for each http request.
You have to setup a separate IUnityContainer instance for the asp.net mvc / web api and another instance of IUnityContainer for Quartz scheduler.
Here is a full working sample
https://github.com/vinodres/DITestingWithQuartz
If you look at QuartzStartup.cs, I have used it to initialize Quartz Scheduler. For simplicity purposes, lets assume IHelloService is a disposable type and it must be disposed at the end of each job as well as at the end of each http request. Here I am creating a separate instance of
IUnityContainer assigned to QuartzContainer and added new extension called QuartzUnityExtention from Quartz.Unity nuget package. Also invoked a .Configure extension method that I created inside another file called unityconfig.cs. This method take Func as a parameter. This parameter allows you to pass different life time manager instances based on the execution path.
Here is QuartzStartup.cs
[assembly: OwinStartup(typeof(DiTestingApp.QuartzStartup))]
namespace DiTestingApp
{
/// <summary>
///
/// </summary>
public class QuartzStartup
{
private static readonly ILog Log = LogManager.GetLogger(typeof(QuartzStartup));
/// <summary>
/// Get the hangfire container.
/// </summary>
private static readonly Lazy<IUnityContainer> QuartzContainer = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
container.AddNewExtension<QuartzUnityExtension>();
container.Configure(() => new HierarchicalLifetimeManager());
return container;
});
/// <summary>
///
/// </summary>
/// <param name="app"></param>
public void Configuration(IAppBuilder app)
{
Log.Info("Quartz Startup Intitializing...");
var container = QuartzContainer.Value;
InitScheduler(container);
Log.Info("Quartz Startup Intialization Complete...");
var properties = new AppProperties(app.Properties);
var cancellationToken = properties.OnAppDisposing;
if (cancellationToken != CancellationToken.None)
{
cancellationToken.Register(() =>
{
QuartzContainer.Value.Dispose();
Log.Info("Quartz container disposed (app pool shutdown).");
});
}
}
private void InitScheduler(IUnityContainer container)
{
try
{
var scheduler = container.Resolve<IScheduler>();
scheduler.Start();
IJobDetail job = JobBuilder.Create<HelloWorldJob>().Build();
ITrigger trigger = TriggerBuilder.Create()
.WithSimpleSchedule(x => x.WithIntervalInSeconds(20).RepeatForever())
.Build();
scheduler.ScheduleJob(job, trigger);
}
catch (Exception ex)
{
Log.Error(ex);
}
}
}
}
A similar setup I have for asp.net mvc / web api dependency resolver configuration. I created a file called UnityMvcActivator.cs, here when I call .Configure extension method, I am passing PerRequestLifetimeManager.
UnityMvcActivator.cs
using System;
using System.Linq;
using System.Web.Http;
using System.Web.Mvc;
using Common.Logging;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Mvc;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(DiTestingApp.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(DiTestingApp.App_Start.UnityWebActivator), "Shutdown")]
namespace DiTestingApp.App_Start
{
/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
private static readonly ILog Log = LogManager.GetLogger(typeof(UnityWebActivator));
/// <summary>
/// Get the hangfire container.
/// </summary>
private static readonly Lazy<IUnityContainer> WebContainer = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
container.Configure(() => new PerRequestLifetimeManager());
return container;
});
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
Log.Info("Web api DI container intializing.");
var container = WebContainer.Value;
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
var resolver = new Microsoft.Practices.Unity.WebApi.UnityDependencyResolver(container);
GlobalConfiguration.Configuration.DependencyResolver = resolver;
Log.Info("Web api DI container intialization complete.");
}
/// <summary>Disposes the Unity container when the application is shut down.</summary>
public static void Shutdown()
{
Log.Info("Web api DI container disposing.");
var container = WebContainer.Value;
container.Dispose();
}
}
}
Now comes the part where you register your types with IUnityContainer. Here is the implementation of configure method inside UnityConfig.cs. Here I have registered IHelloService to use the disposableLifetimeManager delegate. When the delegate is invoked, a proper lifetime manager is supplied depending on your execution path. It will be PerRequestLifetimeManager, if IHelloService is used with in context of asp.net mvc / web api. And it will be HierarchicalLifetimeManager if it is used inside a Quartz Job.
UnityConfig.cs
using System;
using DiTestingApp.Models;
using Microsoft.Practices.Unity;
using Quartz;
using Testing.Scheduler;
namespace DiTestingApp
{
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
public static class UnityConfig
{
/// <summary>
///
/// </summary>
/// <param name="container"></param>
/// <param name="disposableLifetimeManager"></param>
/// <returns></returns>
public static IUnityContainer Configure(this IUnityContainer container, Func<LifetimeManager> disposableLifetimeManager )
{
container.RegisterType<IJob, HelloWorldJob>();
container.RegisterType<IHelloService, HelloService>(disposableLifetimeManager());
return container;
}
}
}
HierarchicalLifetimeManager is used for Quartz execution path, so that any disposable types will be properly disposed at the end of each job.
If Quartz.Unity implementation is not sufficient for your use cases, you can always customize it further.

Replacing Mvvm Lights SimpleIoc with Unity IoC

I am having some trouble to get things up and running after replaced SimpleIoc with the unity IoC. I followed these instructions referring how to implement the IServiceLocator for unity.
However my application fails to function properly. For example I'm unable to get the dataGrids _selectedDevice to be anything else than null. With SimpleIoc, everything worked fine.
Here's my ViewModelLocator:
using System;
using System.Windows;
using GalaSoft.MvvmLight.Ioc;
using GalaSoft.MvvmLight.Messaging;
using Microsoft.Practices.ServiceLocation;
using Microsoft.Practices.Unity;
namespace FxEditorDatabaseStructure.ViewModel
{
/// <summary>
/// This class contains static references to all the view models in the
/// application and provides an entry point for the bindings.
/// </summary>
public class ViewModelLocator
{
#region Constructor
/// <summary>
/// Initializes a new instance of the ViewModelLocator class.
/// </summary>
public ViewModelLocator()
{
// Register the IOC container as SimpleIoc
//ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
// Register Unity as the IOC container
var unityContainer = new UnityContainer();
ServiceLocator.SetLocatorProvider(() => new UnityServiceLocator(unityContainer));
//If we wish use another IoC we must implement the IServiceLocator interface
// Create new UnitOfWork for all the views IOC - CREATED AT registration
//SimpleIoc.Default.Register<IUnitOfWork, UnitOfWork>(true);
unityContainer.RegisterType<IUnitOfWork, UnitOfWork>(new InjectionConstructor(new FxContext()));
/*
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<DeviceDatabaseViewModel>();
SimpleIoc.Default.Register<ProjectDeviceDatabaseViewModel>();
*/
unityContainer.RegisterType<MainViewModel>();
unityContainer.RegisterType<DeviceDatabaseViewModel>();
}
#endregion
#region ViewModels
[NotNull]
public MainViewModel MainViewModel
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
private set { if (value == null) throw new ArgumentNullException(nameof(value)); }
}
[NotNull]
public DeviceDatabaseViewModel DeviceDatabaseViewModel
{
get { return ServiceLocator.Current.GetInstance<DeviceDatabaseViewModel>(); }
private set { if (value == null) throw new ArgumentNullException(nameof(value)); }
}
/// <summary>
/// Retrieves this instance from the application's resources and exposes it to other objects.
/// </summary>
public static ViewModelLocator Instance
{
get
{
return Application.Current.Resources["Locator"] as ViewModelLocator;
}
}
#endregion
#region cleanup
public static void Cleanup()
{
// TODO Clear the ViewModels
}
#endregion
}
}
All the ViewModels call this IoC like this:
private readonly IUnitOfWork _context = ServiceLocator.Current.GetInstance<IUnitOfWork>();
Is there something wrong with this line?
unityContainer.RegisterType<IUnitOfWork, UnitOfWork>(new InjectionConstructor(new FxContext()));
I'm trying to initialise one instance of FxContext and share this to all the ViewModels which all call ServiceLocator.Current.GetInstance<IUnitOfWork>()
EDIT:
Basically I want to be able to use the same UnitOfWork for two different sets of database, like in the following:
var deviceDatabase = new DeviceContext();
var projectDatabase = new ProjectContext();
unityContainer.RegisterType<IUnitOfWork, UnitOfWork>(new InjectionConstructor(deviceDatabase));
unityContainer.RegisterType<IUnitOfWork, UnitOfWork>(new InjectionConstructor(projectDatabase));
Seems like to the answer to register the views similar to SimpleIoc is by following line:
unityContainer.RegisterType<MainViewModel>(new ContainerControlledLifetimeManager());
where the ContainerControlledLifetimeManager() was the key when using RegisterType method.

Ninject throws Activation Exception in a WebApi project with multiple assemblies

My asp.net WebApi project comprises of multiple assemblies for Services, Core and Data Access. In an attempt to use Ninject as my DI container in the project, I added Ninject.Web.Common package from NuGet. Then, I Implemented IDependencyResolver as:
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel) : base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(this.kernel.BeginBlock());
}
}
public class NinjectDependencyScope : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(System.Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
var resolved = this.resolver.Get(serviceType);
return resolved;
}
public System.Collections.Generic.IEnumerable<object> GetServices(System.Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return this.resolver.GetAll(serviceType);
}
public void Dispose()
{
IDisposable disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
}
Here is my Ninject.Web.Common.cs.
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
return kernel;
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind(x =>
x.FromAssembliesInPath(AppDomain.CurrentDomain.RelativeSearchPath)
.SelectAllIncludingAbstractClasses()
.BindDefaultInterface()
.Configure(config => config.InSingletonScope()));
//kernel.Bind(x =>
// {
// x.FromAssembliesMatching("*")
// .SelectAllClasses()
// .BindDefaultInterface()
// .Configure(b => b.InTransientScope());
// });
//kernel.Load()
//kernel.Bind<ISecurityService>().To<SecurityServiceImplementation>();
//kernel.Bind(x => x
// .FromAssembliesMatching("*")
// .SelectAllClasses()
// .BindDefaultInterface());
//.Configure(b => b.InTransientScope()));
//kernel.Load("*.dll");
}
}
exception is
[ActivationException: Error activating IHostBufferPolicySelector
No matching bindings are available, and the type is not self-bindable.
Activation path:
1) Request for IHostBufferPolicySelector
I have used various registrations (commented out) but none work. The break point in NinjectWebCommon.cs -> CreateKernel() method is hit and so does the break point in GetService(System.Type serviceType) method. AppDomain.CurrentDomain.RelativeSearchPath resolves to the bin directory of the app and it contains all the dlls including System.Web.Http.dll which contains the IHostBufferPolicySelector type.
How can I properly use the Ninject.Extensions.Conventions to setup the kernel for type resolution?
From the hints in the answer by Remo and comment by Filip along with a significant amount of debugging time, I found out the use of this.resolver.Get(serviceType) instead of this.resolver.TryGet(serviceType) in GetService() implementation was the culprit in my situation.
I plan a detailed blog post about this but the short of it is that once we have the NinjectDependencyResolver plugged into MVC using the line:
GlobalConfiguration.Configuration.DependencyResolver = new NinjectDependencyResolver(kernel);
and we don't define Framework level dependency bindings (e.g. IHostBufferPolicySelector etc.), an exception is raised by the Get() method for some framework level dependencies when they are not resolved through Ninject. Using TryGet() does not raise an exception and the framework falls back to default dependencies for unresolved (a.ka. null) dependencies like IHostBufferPolicySelector. So, the options are
Use the TryGet() method to resolve dependencies.
Wrap Get in Try/Catch and discard the exception.
Try this post. Instead of catching the Ninject exception, catch the exception for all WebApi calls. http://blog.greatrexpectations.com/2013/05/15/exception-handling-for-web-api-controller-constructors/
In the stacktrace, the constructor where the exception occured would be visible.
There is no class HostBufferPolicySelector so there in no class for which IHostBufferPolicySelector is the default interface. You may try BindAllInterfaces or BindDefaultInterfaces.

Categories