Update 09.08.2018
Unity is being developed here but I haven't had the time to test how it plays with the ASP.NET Core framework.
Update 15.03.2018
This solution is for the specific problem of using ASP.NET Core v1 with Unity while using the .NET Framework 4.5.2 NOT the .NET Core Framework. I had to use this setup since I needed some .Net 4.5.2 DLLs but for anyone starting afresh I would not recommend this approach. Also Unity is not being developed any further (to my knowlage) so I would recommend using the Autofac Framework for new projects. See this Post for more info on how to do that.
Intro
I am building a Web Application using ASP.NET with MVC. This Application depends on certain services (a WCF Service a Datastore service etc). Now to keep things nice and decoupled I want to use a DI (Dependecy Injection) Framework, specifically Unity.
Initial Research
I found this blog post but sadly its not working. The idea though is nice. It basically says that you should not register all the services registered in the ServiceCollection into your own container, but rather reference the default ServiceProvider. So. if something needs to be resolved the default ServiceProvider is called and in case it has no resolution the type will be resolved using your custom UnityContainer.
The Problems
MVC always tries to resolve the Controller with the default ServiceProvider. Also, I noticed that even if the Controller would get resolved correctly, I can never "mix" Dependencies. Now, if I want to use one of my Services but also an IOptions interface from ASP the class can never be resolved because not one of those two containers has resolutions for both types.
What I need
So to recap I need the following things:
A setup where I dont need to copy ASP.NET Dependencies into my UnityContainer
A container which can resolve my MVC Controllers
A container which can resolve "mixed" Dependencies
EDIT:
So the question is how can I achieve these points ?
Environment
project.json:
So after some research I came up with the following solutions to my problems:
Use Unity with ASP
To be able to use Unity with ASP I needed a custom IServiceProvider (ASP Documentation) so I wrote a wrapper for the IUnityContainer which looks like this
public class UnityServiceProvider : IServiceProvider
{
private IUnityContainer _container;
public IUnityContainer UnityContainer => _container;
public UnityServiceProvider()
{
_container = new UnityContainer();
}
#region Implementation of IServiceProvider
/// <summary>Gets the service object of the specified type.</summary>
/// <returns>A service object of type <paramref name="serviceType" />.-or- null if there is no service object of type <paramref name="serviceType" />.</returns>
/// <param name="serviceType">An object that specifies the type of service object to get. </param>
public object GetService(Type serviceType)
{
//Delegates the GetService to the Containers Resolve method
return _container.Resolve(serviceType);
}
#endregion
}
Also I had to change the Signature of the ConfigureServices method in my Startup class from this:
public void ConfigureServices(IServiceCollection services)
to this:
public IServiceProvider ConfigureServices(IServiceCollection services)
Now I can return my custom IServiceProvider and it will be used instead of the default one.The full ConfigureServices Method is shown in the Wire up section at the bottom.
Resolving Controllers
I found this blog post. From it I learned that MVC uses an IControllerActivator interface to handle Controller instantiation. So I wrote my own which looks like this:
public class UnityControllerActivator : IControllerActivator
{
private IUnityContainer _unityContainer;
public UnityControllerActivator(IUnityContainer container)
{
_unityContainer = container;
}
#region Implementation of IControllerActivator
public object Create(ControllerContext context)
{
return _unityContainer.Resolve(context.ActionDescriptor.ControllerTypeInfo.AsType());
}
public void Release(ControllerContext context, object controller)
{
//ignored
}
#endregion
}
Now if a Controller class is activated it will be instatiated with my UnityContainer. Therefore my UnityContainer must know how to Resolve any Controller!
Next Problem: Use the default IServiceProvider
Now if I register services such as Mvc in ASP.NET I normally would do it like this:
services.AddMvc();
Now if I use a UnityContainer all the MVC Dependencies could not be Resolved because they aren't Registered. So I can either Register them (like AutoFac) or I can create a UnityContainerExtension. I opted for the Extension and came up with following two clases :
UnityFallbackProviderExtension
public class UnityFallbackProviderExtension : UnityContainerExtension
{
#region Const
///Used for Resolving the Default Container inside the UnityFallbackProviderStrategy class
public const string FALLBACK_PROVIDER_NAME = "UnityFallbackProvider";
#endregion
#region Vars
// The default Service Provider so I can Register it to the IUnityContainer
private IServiceProvider _defaultServiceProvider;
#endregion
#region Constructors
/// <summary>
/// Creates a new instance of the UnityFallbackProviderExtension class
/// </summary>
/// <param name="defaultServiceProvider">The default Provider used to fall back to</param>
public UnityFallbackProviderExtension(IServiceProvider defaultServiceProvider)
{
_defaultServiceProvider = defaultServiceProvider;
}
#endregion
#region Overrides of UnityContainerExtension
/// <summary>
/// Initializes the container with this extension's functionality.
/// </summary>
/// <remarks>
/// When overridden in a derived class, this method will modify the given
/// <see cref="T:Microsoft.Practices.Unity.ExtensionContext" /> by adding strategies, policies, etc. to
/// install it's functions into the container.</remarks>
protected override void Initialize()
{
// Register the default IServiceProvider with a name.
// Now the UnityFallbackProviderStrategy can Resolve the default Provider if needed
Context.Container.RegisterInstance(FALLBACK_PROVIDER_NAME, _defaultServiceProvider);
// Create the UnityFallbackProviderStrategy with our UnityContainer
var strategy = new UnityFallbackProviderStrategy(Context.Container);
// Adding the UnityFallbackProviderStrategy to be executed with the PreCreation LifeCycleHook
// PreCreation because if it isnt registerd with the IUnityContainer there will be an Exception
// Now if the IUnityContainer "magically" gets a Instance of a Type it will accept it and move on
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
#endregion
}
UnityFallbackProviderStrategy:
public class UnityFallbackProviderStrategy : BuilderStrategy
{
private IUnityContainer _container;
public UnityFallbackProviderStrategy(IUnityContainer container)
{
_container = container;
}
#region Overrides of BuilderStrategy
/// <summary>
/// Called during the chain of responsibility for a build operation. The
/// PreBuildUp method is called when the chain is being executed in the
/// forward direction.
/// </summary>
/// <param name="context">Context of the build operation.</param>
public override void PreBuildUp(IBuilderContext context)
{
NamedTypeBuildKey key = context.OriginalBuildKey;
// Checking if the Type we are resolving is registered with the Container
if (!_container.IsRegistered(key.Type))
{
// If not we first get our default IServiceProvider and then try to resolve the type with it
// Then we save the Type in the Existing Property of IBuilderContext to tell Unity
// that it doesnt need to resolve the Type
context.Existing = _container.Resolve<IServiceProvider>(UnityFallbackProviderExtension.FALLBACK_PROVIDER_NAME).GetService(key.Type);
}
// Otherwise we do the default stuff
base.PreBuildUp(context);
}
#endregion
}
Now if my UnityContainer has no Registration for something it just ask the default Provider for it.
I learned all of this from several different articles
MSDN Unity article
Auto-Mocking Unity Container Extension
Custom Object Factory Unity Extension
The nice thing about this approach is that I can also "mix" Dependencies now. If I need any of my Services AND an IOptions Interface from ASP my UnityContainer will resolve all of these Dependencies and Inject them into my Controller !!! The only thing to remember is that if I use any of my own Dependencies I have to register my Controller class with Unity because the default IServiceProvider can no longer Resolve my Controllers Dependencies.
Finally: Wire up
Now in my project I use different services (ASP Options, MVC with options). To make it all work my ConfigureServices Method looks like this now:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
// Add all the ASP services here
// #region ASP
services.AddOptions();
services.Configure<WcfOptions>(Configuration.GetSection("wcfOptions"));
var globalAuthFilter = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
services.AddMvc(options => { options.Filters.Add(new AuthorizeFilter(globalAuthFilter)); })
.AddJsonOptions
(
options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()
);
// #endregion ASP
// Creating the UnityServiceProvider
var unityServiceProvider = new UnityServiceProvider();
IUnityContainer container = unityServiceProvider.UnityContainer;
// Adding the Controller Activator
// Caution!!! Do this before you Build the ServiceProvider !!!
services.AddSingleton<IControllerActivator>(new UnityControllerActivator(container));
//Now build the Service Provider
var defaultProvider = services.BuildServiceProvider();
// Configure UnityContainer
// #region Unity
//Add the Fallback extension with the default provider
container.AddExtension(new UnityFallbackProviderExtension(defaultProvider));
// Register custom Types here
container.RegisterType<ITest, Test>();
container.RegisterType<HomeController>();
container.RegisterType<AuthController>();
// #endregion Unity
return unityServiceProvider;
}
Since I learned most of what I know about DI in the past week I hope I didnt break any big Pricipal/Pattern if so please tell me!
For ASP.Net Core 2.0, 2.1, 2.2, 3.1 and Unity there is official solution available from Unity authors as NuGet package here: NuGetPackage
Here is Git repository with samples: Git repo
Usage is very simple (from Git repo homepage):
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseUnityServiceProvider() <---- Add this line
.UseStartup<Startup>()
.Build();
And here is example with Unity DI for ASP.Net Core.
I am using this solution in my ASP.Net Core application and works good.
Related
I have a Web API implementation in ASP.NET Core and I'd like to use the included Dependency Injection.
In addition I have late binded assemblies, where I have to load a Type and create an instance of it, which can have dependencies to the main application.
I am trying to load dynamic resources from Assemblies I do not know while startup. So I am using Assembly.Load("name") and look up factory types, that give me the resource reader implementation of the Assembly.
So I know the type I need to create an instance of, but I cannot register it to the IServiceCollection and therefore cannot create instances with the ServiceProvider.
So I tried to register my found types to the IServiceCollection which was provided by the framework. For what I registered the ServiceCollection within itself.
// Within Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IServiceCollection>(services);
}
// A service to register new dependencies later on
public class ServiceRegistrationService : IServiceRegistrationService
{
public IServiceCollection Services { get; }
public IServiceRegistrationService RegisterSelfTransient(Type type)
{
Services.AddTransient(type);
return this;
}
}
After calling this method like:
ServiceRegistrationService.RegisterSelfTransient(typeof(MyConcreteType));
I'd expect the IServiceProvider to resolve a new instance of my type.
Is there a way to register services after leaving the ConfigureServices(IServiceCollection services) method?
After execution of WebApplicationBuilder.Build() in Program.cs's top-level statements, the IServiceCollection turns to read-only one:
public IHost Build()
{
...
// Prevent further modification of the service collection now that the provider is built.
_serviceCollection.MakeReadOnly();
...
}
So it seems no further changes could be introduced after that.
I have an .NET MVC 5 .NET Framework Application which I am converting to .NET Core 2.1
I have a custom action filter which in .NET Framework version was registered as a Global Filter in a Filterconfig class like below:
public class FilterConfig
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new MyCustomActionFilter());
}
}
Within the custom action filter in the .NET version I was using Service Locator pattern (I know it can be considered an anti pattern) as below:
var myService = DependencyResolver.Current.GetService<IMyService>();
I am using Simple Injector for DI and everything works fine in the .NET Version. With the .NET Core version I am trying to get the same functionality working but myService is always null
I am still using Simple Injector (as all the other projects in the solution use it and they are not getting move to .NET Core projects (only the web one is).
My Startup.cs class has this code:
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new MyCustomActionFilter());
});
SimpleInjectorConfig.IntegrateSimpleInjector(services, container);
At my service layer I have a SimpleInjector Registartion class that gets called from Web Layer - it then calls down to DAL Layer to do Registration
public class SimpleInjectorRegistration
{
public static void RegisterServices(Container container)
{
container.Register<IMyService, MyService>();
//further code removed for brevity
When I run the application with a breakpoint in the Custom Filter and a breakpoint in this RegisterServices method I can see the breakpoint in the RegisterServices method gets hit first and then the breakpoint in the Custom Filter - this made me think everything was wired up in the container correctly.
However I am trying to do the below again in the custom filter with .NET Core Service Locator pattern
var myService = filterContext.HttpContext.RequestServices.GetService<IMyService>();
but the result is always null?
Is there something I have missed in this setup?
------------ UPDATE -------------------
Based on Stevens comment I added a constructor to my action filter and passed in the Simple Injector container.
So My Startup class now is:
public class Startup
{
//Simple Injector container
private Container container = new Container();
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.Configure<MvcOptions>(options =>
{
options.Filters.Add(new MyCustomActionFilter(container));
My Custom filter now is like below with constructor added:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly IMyService _myService;
public MyCustomActionFilter(Container container)
{
_myService = container.GetService<IMyService>();
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//actual code of custom filter removed - use of MyService
I set a breakpoint on the Constructor of MyCustomActionFilter and I can see it getting hit but I get an Error thrown:
SimpleInjector.ActivationException: 'The IDbContext is registered as 'Async Scoped' lifestyle, but the instance is requested outside the context of an active (Async Scoped) scope.'
MyService has a Dependency on the DbContext which is injected into it (it is doing work saving and retrieving data from DB.
For the DB Context I registered it as below:
public class SimpleInjectorRegistration
{
public static void RegisterServices(Container container, string connectionString)
{
container.Register<IDbContext>(() => new MyDbContext(connectionString),
Lifestyle.Scoped);
}
}
There are some significant changes between how to integrate Simple Injector in the old ASP.NET MVC and the new ASP.NET Core. In the old system, you would be able to replace the IDependencyResolver. ASP.NET Core, however, contains a completely different model, with its own internal DI Container. As it is impossible to replace that built-in container with Simple Injector, you will have the two containers run side-by-side. In that case the built-in container will resolve framework and third-party components, where Simple Injector will compose application components for you.
When you call HttpContext.RequestServices.GetService, you will be requesting the built-in container for a service, not Simple Injector. Adding the IMyService registration to the built-in container, as TanvirArjel's answer suggests, might seem to work at first, but that completely skips Simple Injector from the equation, which is obviously not an option, as you wish to use Simple Injector as your application container.
To mimic the Service Locator-like behavior you had before, you will have to inject the SimpleInjector.Container into your filter, as follows:
options.Filters.Add(new MyCustomActionFilter(container));
It would be an error, however, to call the container from within the constructor, as you are showing in your question:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly IMyService _myService;
public MyCustomActionFilter(Container container)
{
_myService = container.GetService<IMyService>(); // NEVER DO THIS!!!
}
...
}
WARNING: You should never resolve from the container from the constructor. Or in more general: you should never use any injected dependency from inside the constructor. The constructor should only store the dependency.
As Mark Seemann explained, injection constructors should be simple. In this case, it even gets worse because:
During the time that the constructor of MyCustomActionFilter is invoked, there is no active scope, and IMyService can't be resolved
Even if IMyService could be resolved, MyCustomActionFilter is a Singleton and storing IMyService in a private field will cause a hidden Captive Dependency. This could lead to all sorts of trouble.
Instead of storing the resolved, IMyService dependency, you should store the Container dependency:
public class MyCustomActionFilter : ActionFilterAttribute
{
private readonly Container _container;
public MyCustomActionFilter(Container container)
{
_container = container;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
myService = container.GetService<IMyService>();
//actual code of custom filter removed - use of MyService
}
}
During the time that OnActionExecuting is called, there will be an active Simple Injector Scope, which will allows IMyService to be resolved. On top of that, as IMyService is not stored in a private field, it will not be cached and will not cause a Captive Dependency.
In your question you referred to the Service Locator anti-pattern. Whether or not the injection of the Container into your filter is in fact an implementation of the Service Locator anti-pattern depends on where the filter is located. As Mark Seemann puts it:
A DI container encapsulated in a Composition Root is not a Service Locator - it's an infrastructure component.
In other words, as long as the filter class is located inside your Composition Root, you are not applying the Service Locator anti-pattern. This does mean, however, that you must make sure that the filter itself contains as little interesting behavior as possible. That behavior should all be moved to the service that the filter resolves.
As #Steven points out, the built-in container will resolve framework and third-party components, where Simple Injector will compose application components for you. For built-in container, it could not resolve the service from simple injector. For simple injector, you could try EnableSimpleInjectorCrossWiring to resolve services from built-in container.
For options.Filters.Add, it also accepts MyCustomActionFilter instance, without resigering Container as depedence into MyCustomActionFilter, you could try register MyCustomActionFilter in sample injector, and then pass this instance to options.Filters.Add.
Register Services
private void InitializeContainer(IApplicationBuilder app)
{
// Add application presentation components:
container.RegisterMvcControllers(app);
container.RegisterMvcViewComponents(app);
// Add application services. For instance:
container.Register<IMyService, MyService>(Lifestyle.Scoped);
container.Register<MyCustomActionFilter>(Lifestyle.Scoped);
// Allow Simple Injector to resolve services from ASP.NET Core.
container.AutoCrossWireAspNetComponents(app);
}
add MyCustomActionFilter
services.Configure<MvcOptions>(options =>
{
using (AsyncScopedLifestyle.BeginScope(container))
{
options.Filters.Add(container.GetRequiredService<MyCustomActionFilter>());
}
});
#region SampleInjector
IntegrateSimpleInjector(services);
#endregion
Note If you specify container.Options.DefaultScopedLifestyle = new AsyncScopedLifestyle();, you will need using (AsyncScopedLifestyle.BeginScope(container)) when you call container.GetRequiredService<MyCustomActionFilter>().
I'm new to C#/ASP coming from a Java world. I've read this article: https://docs.asp.net/en/latest/fundamentals/dependency-injection.html#service-lifetimes-and-registration-options which wisely warns about the dangers associated with injecting a dependency with a smaller scope. Unfortunately it does not explain how to solve this issue in C#/ASP.
In Java there's a concept of Provider
interface Provider<T> { T get(); }
which, among other things helps to solve the scoping issue:
whenever a binding for some type T is register we can inject an automatically generated instance of Provider<T> instead of T and then get an instance of T whenever it is needed: an automatically generated Provider makes sure that we get an instance appropriate for the current scope (whatever this scope is: HTTP request, HTTP session or other custom scopes). The standard DI framework built into ASP.NET core does not have anything like this, but I thought in C# it should be very easy to implement as C# generics don't suck like java's do (https://docs.oracle.com/javase/tutorial/java/generics/erasure.html). So I've created the following class:
public class Provider<T>: IProvider<T> {
private readonly IServiceProvider serviceProvider;
public Provider(IServiceProvider serviceProvider) {
this.serviceProvider = serviceProvider;
}
public T IProvider<T>.Get() {
return serviceProvider.GetService<T>();
}
}
and I attemtped to use it the following way:
public class SingletonService : ISingletonService {
private readonly IProvider<IScopedService> scopedServiceProvider;
public SingletonService(IProvider<IScopedService> scopedServiceProvider) {
this.scopedServiceProvider = scopedServiceProvider;
}
public string PerformMyTask() {
var scopedDependency = scopedServiceProvider.Get();
// do something with scopedDependency to verify we get instances
// appropriate for the current scope
}
}
and in my Startup class:
public void ConfigureServices(IServiceCollection services) {
services.AddSingleton<ISingletonService, SingletonService>();
services.AddScoped<IScopedService, ScopedService>();
services.AddTransient<IProvider<IScopedService>, Provider<IScopedService>>();
// other bindings here
}
Unfortunately this does not work the way I intended as IServiceProvider instance seems to be also scoped to the current HTTP request and I get exactly the same instance of ScopedDependency from my provider during processing of different requests :(
Any hints how can I solve this problem?
Is there any "higher level" object than ServiceProvider maybe, bound roughly to application lifecycle (not to the current request) that creates instances of request scoped objects (or of ServiceProvider itself) that I can inject into my Provider objects instead of ServiceProvider? For example in Java if I use google Guice as a DI framework there is an Injector object, usually created at the startup of an application which holds all the type bindings and has a method
<T> T getInstance(Class<T> type);
which checks what is the current scope and returns a corresponding instance.
edit:
I think that one possible way to do it would be to get a new reference to instance of ServiceProvider each time in the Proivder<T>.Get() method instead of injecting in the constructor and storing as an instance var. This way my components would still not be polluted with a reference to the framework specific IServiceProvider as it would be hidden from them in the implementation of Provider<T> that they access via the abstract IProvider<T> interface. I can't however find on the web if it's possible to get such a reference from my Provider class and how to do this. Any pointers in this direction would be appreciated :)
Thanks!
ok, found it:
public class Provider<T> : IProvider<T> {
IHttpContextAccessor contextAccessor;
public Provider(IHttpContextAccessor contextAccessor) {
this.contextAccessor = contextAccessor;
}
T IProvider<T>.Get() {
return contextAccessor.HttpContext.RequestServices.GetService<T>();
}
}
and in Startup:
public void ConfigureServices(IServiceCollection services) {
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton<ISingletonService, SingletonService>();
services.AddScoped<IScopedService, ScopedService>();
services.AddTransient<IProvider<IScopedService>, Provider<IScopedService>>();
// other bindings
}
:)
see https://github.com/aspnet/Hosting/issues/793 for more details about using and registering HttpContextAccessor
We're trying to create a delivery recipe based on HotTowel Angular + Breeze. The dependency injection part in the SPA app is well covered but trying to resolve the BreezeController through Unity proves to be a challenge. I may lack one thing in there but haven't figured it out.
So far here's what we've done:
Unity bootstrapper for ASP.NET MVC 3.5.1404 is installed
Added a new controller called LoggingController which applies the BreezeController attribute
On this controller set a repository dependency through the constructor
All's good and clean, Unity container is activated through UnityMvcActivator.cs which looks like this:
using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(CC.Web.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(CC.Web.App_Start.UnityWebActivator), "Shutdown")]
namespace CC.Web.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();
}
}
}
The container is configured through UnityConfig.cs
using System;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;
using System.Web.Http;
namespace CC.Web.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)
{
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
container.LoadConfiguration();
// TODO: Register your types here
// container.RegisterType<IProductRepository, ProductRepository>();
}
}
}
Upon calling the controller it seems Unity is not in charge as it throws an error about not finding an empty constructor.
I would assume DependencyResolver.SetResolver(new UnityDependencyResolver(container)); would properly tell which resolver to use like in Mike Wasson blog post mentionned by Steve: config.DependencyResolver = new UnityResolver(container);. UnityDependencyResolver does implement IDependencyResolver.
So what I'm asking, assuming that installing the Nuget Package is only what is needed to hook Unity as a resolver, is there a way to use Unity as a Resolver for Breeze controllers or should we simply use the Breeze controllers as facade to a properly IOC built component? I'd rather have the resolving done through Unity transparently instead of going through a facade.
You will want the Unity.AspNet.WebApi package for resolving WebApi controllers (including Breeze controllers).
You also need to tell WebApi to use Unity to resolve dependencies. Usually this is done in some static method that you call from Global.asax.cs. This blog post by Mike Wasson lays it all out.
The Unity.WebAPI Github page suggests using the UnityConfig.RegisterComponents()method for registering your repositories.
I would like to understand how i can resolve a unity named type registration within an MVC4 application.
I am using "Unity 3.0" and the "Unity boostrapper for ASP.NET MVC".
I understand that unity is registered with the DependencyResolver and so i can use the dependency resolver methods to get an instance of an registered type.
This works fine when I want to get a simple registration back.
e.g
//Registration
container.RegisterType<IFootballer, VanPersey>();
//Instantiation
var footballer1 = DependencyResolver.Current.GetService<IFootballer>();
But on an occasion when I want to get a reference to a named type registration it doesn't appear that the IDependencyResolver interface provides the appropriate methods to get named type registration instances.
If I had access to the unity container directly I would do something like the following:
//Registration
container.RegisterType<IFootballer, VanPersey>("Attacker" );
container.RegisterType<IFootballer, NemanjaVidic>("Defender");
//Instantiation
unityContainer.Resolve<IFootballer, Footballer>("Attacker")
So my question is , what is the most appropriate way to use unity in an MVC app in order to get an instance of a named registration. ie is there access to the unity comtainer?
Note that this question is not for any production implementation, I am looking at Unity (and IoC containers for the first time) and tying to get a better understanding.
I understand in production I would more than likely be passing in the dependencies through the controllers constructors, which actually leads me to another question.
How would it be possible to indicate which named type you wanted to resolve when using controller constructor injection in the following example:
//Registration
container.RegisterType<IFootballer, VanPersey>("Attacker" );
container.RegisterType<IFootballer, NemanjaVidic>("Defender");
//Instantiation
public HomeController(IFootballer footballer)
Most probably the container itself is also registered so that the resolver can resolve it:
var container = DependencyResolver.Current.GetService<IUnityContainer>();
var vanPersey = container.RegisterType<IFootballer, VanPersey>("Attacker" );
Haven't tried it with the resolver but it always worked like that with the ServiceLocator.
Incase this helps anyone else wanting to do the same thing, I found the following:
When using "Unity 3.0" and the "Unity boostrapper for AP.NET MVC" I found that un the UnityConfig class that it exposes a GetConfiguredContainer method in which you can directly access the unity container without having to use the dependency resolver.
Snippet from UnityConfig
/// <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
}
So that allowed me to access the Unity container directly to obtain named type instances.
var footballer1 = UnityConfig.GetConfiguredContainer().Resolve<IFootballer>("Attacker");
var footballer2 = UnityConfig.GetConfiguredContainer().Resolve<IFootballer>("Defender");