OWIN Startup Class - dependency-injection

Can someone please tell me the exact role of the OWIN startup class. Basically what I am looking for :
Whats its purpose
When is it called, it is just once or per request
Is this a good place to configure my Dependency Injection library.

Owin is designed to be pluggable deisgn. there are a set of services which you can change/replace from the configuration. For example in the following configuration, i have
enabled webapi
Enabled Signalr
Enabled Attribute Based routing for Signalr
Configured default Dependency Resolver
Replaced Logging service with custom logger
So , this way, you can configure the complete configuration. It will be called only once at startup. You can set/use dependency resolver and configure it here, but that depends mainly on your overall design.
public class OwinStartup
{
//initialize owin startup class and do other stuff
public void Configuration(IAppBuilder app)
{
app.UseWelcomePage("/");
//var container = new UnityContainer();
HttpConfiguration httpConfiguration = new HttpConfiguration();
httpConfiguration.Routes.MapHttpRoute(
name: "MyDefaultApi",
routeTemplate: "api/v2/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//Maps the attribute based routing
httpConfiguration.MapHttpAttributeRoutes();
//Set the unity container as the default dependency resolver
httpConfiguration.DependencyResolver = new UnityWebApiDependencyResolver(new UnityContainer());
//replace (or add) the exception logger service to custom Logging service
httpConfiguration.Services.Replace(typeof(IExceptionLogger), new ExLogger());
app.UseWebApi(httpConfiguration);
//Add Signalr Layer
app.MapSignalR(new HubConfiguration
{
EnableJSONP = true,
EnableDetailedErrors = true
});
}
public class ExLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
base.Log(context);
//do something
}
}
}

Related

How to configure Autofac and SignalR in a MVC 5 application

I am trying to configure an MVC 5 application to use SignalR 2.2.x and inject a service into my NotificationsHub.
We are using Autofac for MVC but I am not sure on how to correctly configure this.
Autofac documentation exists for NuGet Autofac.Integration.SignalR (3.0.2) and Autofac.Integration.Mvc (3.3.4).
What I am doing so far is register the hubs via:
ContainerBuilder builder = new ContainerBuilder();
// Register MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<ServiceForSignalRHub>().AsImplementedInterfaces();
builder.RegisterType<...>().AsImplementedInterfaces();
builder.RegisterHubs(Assembly.GetExecutingAssembly());
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
However the call to .SetResolver(...) is ambigious as it exists in both MVC and SignalR integration packages. Now what? I am unable to confirm if the contructor injection of my service works for the Hub I am using.
EDIT
I can configure MVC5 with Autofac just fine. Where I get lost is how to do the same with SignalR, using the Autofac Signal integration NuGet.
Please see below.
This is my startup class:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var defaultFactory = LogManager.Use<DefaultFactory>();
defaultFactory.Directory("#D:\\NServiceBus\\ );
defaultFactory.Level(LogLevel.Debug);
var container = ConfigureAutofac(app);
ConfigureServiceBus(container, app);
app.UseAutofacMiddleware(container); // REGISTER WITH OWIN
app.UseAutofacMvc();
ConfigureAuth(app);
GlobalConfiguration.Configuration.UseSqlServerStorage("hangfire");
ConfigureSignalR(app);
}
}
This is the part where I configure SignalR:
public partial class Startup
{
public void ConfigureSignalR(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterHubs(Assembly.GetExecutingAssembly()).PropertiesAutowired();
builder.RegisterType<MaintenanceService>().As<IMaintenanceService>().PropertiesAutowired();
var container = builder.Build();
//var container = new AutofacContainer().Container;
var resolver = new AutofacDependencyResolver(container);
// Any connection or hub wire up and configuration should go here
app.MapSignalR(new HubConfiguration
{
Resolver = resolver,
EnableJSONP = true,
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
});
builder.RegisterInstance(resolver.Resolve<IConnectionManager>());
}
}
How can this be correctly done?
You should tell SignalR explicitly to use the AutofacDependencyResolver when you are mapping it.
I assume that you know that in your Startup class you have to call app.MapSignalR();
When you are mapping it, you should tell it to use the custom dependency resolver (the AutofacDependencyResolver).
Here's how I do it:
var resolver = new AutofacDependencyResolver(container);
app.MapSignalR(new HubConfiguration
{
Resolver = resolver
});
This way, you are telling SignalR directly which dependency resolver to use.
I have a GitHub repo for SignalR Dependency Injection, but it's not configured to use MVC. Still, I think it will give you a hint in how to create your configuration.
Note: If you are using the OWIN Middleware, be sure not to use the GlobalHost static property AT ALL since it will have massive inconsistencies.
A common error in OWIN integration is use of the GlobalHost. In OWIN
you create the configuration from scratch. You should not reference
GlobalHost anywhere when using the OWIN integration.
Again, check the repo I gave you to see how to do this.
Hope this helps:)
Best of luck!
I ended up with this (pay attention to comments):
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
IContainer container = AutofacConfig(app);
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacWebApi(GlobalConfiguration.Configuration);
var hubConfiguration = new Microsoft.AspNet.SignalR.HubConfiguration()
{
// Resolve presolver from container
Resolver = container.Resolve<Microsoft.AspNet.SignalR.IDependencyResolver>(),
};
app.MapSignalR(hubConfiguration);
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
_
private static IContainer AutofacConfig(IAppBuilder app)
{
var builder = new ContainerBuilder();
RegisterSignalR(builder);
return builder.Build();
}
_
private static void RegisterSignalR(ContainerBuilder builder)
{
// Register Autofac resolver into container to be set into HubConfiguration later
builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
.As<Microsoft.AspNet.SignalR.IDependencyResolver>()
.SingleInstance();
// Register ConnectionManager as IConnectionManager so that you can get
// hub context via IConnectionManager injected to your service
builder.RegisterType<Microsoft.AspNet.SignalR.Infrastructure.ConnectionManager>()
.As<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>()
.SingleInstance();
// Register hubs one by one
builder.RegisterType<MessageNotificationsHub>().ExternallyOwned();
builder.RegisterType<SystemNotificationsHub>().ExternallyOwned();
}
Thanks to #Nathan and his answer (originally found here) and logical thinking to figure out to register ConnectionManager as IConnectionManager
Install nuget package Autofac.SignalR, for example:
<package id="Autofac.SignalR" version="3.0.2" targetFramework="net471" />
Register your hubs
// during creation of the IContainer, register signalr hubs automatically
var executingAssembly = Assembly.GetExecutingAssembly();
builder.RegisterHubs(executingAssembly);
// alternatively register hubs individually
// ExternallyOwned() ensures SignalR is allowed to control disposal of the hubs rather than Autofac.
builder.RegisterType<NotificationHub>().ExternallyOwned();
Set signalr service locator
// replace the Signalr dependency resolver once your IContainer 'container' is ready
GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);
// or this can alternatively be set in the HubConfiguration instance when using OWIN IAppBuilder map.RunSignalR(hubConfiguration);
var hubConfiguration = new HubConfiguration
{
Resolver = new AutofacDependencyResolver(container),
//...
}
For more information:
https://autofaccn.readthedocs.io/en/latest/integration/signalr.html
https://learn.microsoft.com/en-us/aspnet/signalr/overview/advanced/dependency-injection

How can I get started with ASP.NET (5) Core and Castle Windsor for Dependency Injection?

Background:
I've used Castle Windsor with Installers and Facilities according to the Castle Windsor tutorial with earlier versions of MVC (pre-6) and WebAPI.
ASP.NET (5) Core has included some Dependency Injection support but I still haven't figured out exactly how to wire it up, and the few samples I have found look a lot different than how I've used it before (with the installers/facilities). Most examples predate ASP.NET (5) cores recent release and some seem to have outdated information.
It seems to have changed quite radically from the previous versions composition root setup, and not even Microsoft.Framework.DependencyInjection.ServiceProvider can resolve all of the dependencies when I set it as the Castle Windsor DI fallback. I'm still digging into the details but there isn't much up to date information.
My attempt to use Castle Windsor for DI
I've found an adapter like this: Github Castle.Windsor DI container.
Startup.cs
private static IWindsorContainer container;
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)
{
container = new WindsorContainer();
app.UseServices(services =>
{
// ADDED app.ApplicationServices FOR FALLBACK DI
container.Populate(services, app.ApplicationServices);
container.BeginScope();
return container.Resolve<IServiceProvider>();
});
// ... default stuff
WindsorRegistration.cs
I added a few lines to add a Castle Windsor ILazyComponentLoader fallback.
using Castle.MicroKernel.Lifestyle;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.Resolvers.SpecializedResolvers;
using Castle.Windsor;
using Microsoft.Framework.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace Notes.Infrastructure
{
/// <summary>
/// An adapted current autofac code to work with Castle.Windsor container.
/// https://github.com/aspnet/Home/issues/263
/// </summary>
public static class WindsorRegistration
{
public static void Populate(
this IWindsorContainer container,
IEnumerable<IServiceDescriptor> descriptors,
IServiceProvider fallbackProvider // ADDED FOR FALLBACK DI
)
{
// ADDED FOR FALLBACK DI
// http://davidzych.com/2014/08/27/building-the-castle-windsor-dependency-injection-populator-for-asp-net-vnext/
// Trying to add a fallback if Castle Windsor doesn't find the .NET stuff
var fallbackComponentLoader = new FallbackLazyComponentLoader(fallbackProvider);
container.Register(Component.For<ILazyComponentLoader>().Instance(fallbackComponentLoader));
// Rest as usual from the Github link
container.Register(Component.For<IWindsorContainer>().Instance(container));
container.Register(Component.For<IServiceProvider>().ImplementedBy<WindsorServiceProvider>());
container.Register(Component.For<IServiceScopeFactory>().ImplementedBy<WindsorServiceScopeFactory>());
container.Kernel.Resolver.AddSubResolver(new CollectionResolver(container.Kernel));
Register(container, descriptors);
}
private static void Register(
IWindsorContainer container,
IEnumerable<IServiceDescriptor> descriptors)
{
foreach (var descriptor in descriptors)
{
if (descriptor.ImplementationType != null)
{
// Test if the an open generic type is being registered
var serviceTypeInfo = descriptor.ServiceType.GetTypeInfo();
if (serviceTypeInfo.IsGenericTypeDefinition)
{
container.Register(Component.For(descriptor.ServiceType)
.ImplementedBy(descriptor.ImplementationType)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
else
{
container.Register(Component.For(descriptor.ServiceType)
.ImplementedBy(descriptor.ImplementationType)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
}
else if (descriptor.ImplementationFactory != null)
{
var service1 = descriptor;
container.Register(Component.For(descriptor.ServiceType)
.UsingFactoryMethod<object>(c =>
{
var builderProvider = container.Resolve<IServiceProvider>();
return
service1.ImplementationFactory(builderProvider);
})
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
else
{
container.Register(Component.For(descriptor.ServiceType)
.Instance(descriptor.ImplementationInstance)
.ConfigureLifecycle(descriptor.Lifecycle)
.OnlyNewServices());
}
}
}
private static ComponentRegistration<object> ConfigureLifecycle(
this ComponentRegistration<object> registrationBuilder,
LifecycleKind lifecycleKind)
{
switch (lifecycleKind)
{
case LifecycleKind.Singleton:
registrationBuilder.LifestyleSingleton();
break;
case LifecycleKind.Scoped:
registrationBuilder.LifestyleScoped();
break;
case LifecycleKind.Transient:
registrationBuilder.LifestyleTransient();
break;
}
return registrationBuilder;
}
private class WindsorServiceProvider : IServiceProvider
{
private readonly IWindsorContainer _container;
public WindsorServiceProvider(IWindsorContainer container)
{
_container = container;
}
public object GetService(Type serviceType)
{
return _container.Resolve(serviceType);
}
}
private class WindsorServiceScopeFactory : IServiceScopeFactory
{
private readonly IWindsorContainer _container;
public WindsorServiceScopeFactory(IWindsorContainer container)
{
_container = container;
}
public IServiceScope CreateScope()
{
return new WindsorServiceScope(_container);
}
}
private class WindsorServiceScope : IServiceScope
{
private readonly IServiceProvider _serviceProvider;
private readonly IDisposable _scope;
public WindsorServiceScope(IWindsorContainer container)
{
_scope = container.BeginScope();
_serviceProvider = container.Resolve<IServiceProvider>();
}
public IServiceProvider ServiceProvider
{
get { return _serviceProvider; }
}
public void Dispose()
{
_scope.Dispose();
}
}
}
}
First hiccup and resolution attempt
From that example I was getting:
An exception of type 'Castle.MicroKernel.ComponentNotFoundException' occurred in Castle.Windsor.dll but was not handled in user code
Additional information: No component for supporting the service Microsoft.Framework.Runtime.IAssemblyLoaderEngine was found
It wasn't available looking in the debugger at the Castle Fallback - Microsoft.Framework.DependencyInjection.ServiceProvider (table of services).
From http://davidzych.com/tag/castle-windsor/ I have tried to add a Fallback since Windsor couldn't resolve all of the ASP.NET dependencies.
FallbackLazyComponentLoader.cs
/// <summary>
/// https://github.com/davezych/DependencyInjection/blob/windsor/src/Microsoft.Framework.DependencyInjection.Windsor/FallbackLazyComponentLoader.cs
/// </summary>
public class FallbackLazyComponentLoader : ILazyComponentLoader
{
private IServiceProvider _fallbackProvider;
public FallbackLazyComponentLoader(IServiceProvider provider)
{
_fallbackProvider = provider;
}
public IRegistration Load(string name, Type service, IDictionary arguments)
{
var serviceFromFallback = _fallbackProvider.GetService(service);
if (serviceFromFallback != null)
{
return Component.For(service).Instance(serviceFromFallback);
}
return null;
}
}
It was seemingly necessary (to inject all the .NET dependencies)
I could comment out startup.cs app.UseBrowserLink(); to get rid of the IAssemblyLoaderEngine exception.
if (string.Equals(env.EnvironmentName, "Development", StringComparison.OrdinalIgnoreCase))
{
//app.UseBrowserLink(); //
Now I run into an exception:
An exception of type 'System.Reflection.TargetInvocationException' occurred in mscorlib.dll but was not handled in user code
Trying to get the service: {Name = "IUrlHelper" FullName = "Microsoft.AspNet.Mvc.IUrlHelper"}
public IRegistration Load(string name, Type service, IDictionary arguments)
{
var serviceFromFallback = _fallbackProvider.GetService(service);
How to move forward?
What is wrong with this attempt to wire up Castle Windsor DI into ASP.NET (5) Core?
For now I don't think you can use Castle Windsor Container as the DI container because Windsor doesn't support the new DNVM. But AutoFac does and they follow the same rule.
In the Startup.cs there is a ConfigureServices method whose return type is void. You can change the return type to ISerivceProvider and return a concrete IServiceProvider, the system will use the new IServiceProvider as the default DI container. Below is the AutoFac example.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));
services.AddMvc();
var builder = new ContainerBuilder();
AutofacRegistration.Populate(builder, services);
var container = builder.Build();
return container.Resolve<IServiceProvider>();
}
The other DI adapters also implemented the similar interfaces. You can try yourself, but note AutoFac is in beta5 now so you need to make some adjustment to make your application run.
Hope this helps
There is a lot going on in your question, and to be honest I don't understand all of it.
However, there is a working Castle Windsor composition root in MvcSiteMapProvider that you are welcome reverse-engineer. Follow these steps to get a working composition root demo project for Windsor:
Create a new MVC 5 project.
Install MvcSiteMapProvider.MVC5.DI.Windsor.
Analyze the following files for the basic structure:
/App_Start/DIConfig.cs
/App_Start/CompositionRoot.cs
/DI/InjectableControllerFactory.cs
/DI/Windsor/WindsorDependencyInjectionContainer.cs
/DI/Windsor/Installers/MvcInstaller.cs
/DI/Windsor/Installers/MvcSiteMapProviderInstaller.cs
Once you have this working configuration, you can then refactor it and add to it to suit your application's needs.
As I recall, there weren't any changes required to make the MVC 4 DI configuration work with MVC 5. So, the problem you are running into is most likely one of the following:
You are using a 3rd party DI component that is not compatible with MVC 5.
You are using DependencyResolver, and your configuration doesn't include the necessary code to resolve the dependencies of MVC 5.
You are using advanced features of Castle Windsor that we are not using, and have them misconfigured in some way.
ControllerFactory vs DependencyResolver
Do note that according to Dependency Injection in .NET by Mark Seemann (which I highly recommend), it is ill-advised to use IDependencyResolver with Castle Windsor because it guarantees resource leaks. In fact, this is probably the most compelling argument that he makes for his reasoning for declaring service locator as anti-pattern.
The recommended approach is to use IControllerFactory as the integration point into MVC, which implements a ReleaseController method to solve this issue.
So looking at your code, literally all of it can be replaced by Castle.Windsor.MsDependencyInjection library.
Add Castle.Windsor.MsDependencyInjection to your project then use like so:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// Normal component registration can go here...
return WindsorRegistrationHelper.CreateServiceProvider(yourWindsorContainer, services);
}

Autofac Azure Mobile Service integration issue

I gets '..make sure that the controller has a parameterless public constructor autofac..'
My controller:
public class AccountController : ApiController
{
private IAccountService _accountService;
public AccountController(IAccountService accountService)
{
_accountService = accountService;
}
...
}
My autofac configuration:
protected void Application_Start()
{
var builder = new ContainerBuilder();
var config = GlobalConfiguration.Configuration;
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<AccountService>().As<IAccountService>().InstancePerRequest();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
Whats wrong with my code?
Full error message:
Exception=System.InvalidOperationException: An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor. ---> Autofac.Core.DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'MyProj.Api.Controllers.AccountController' can be invoked with the available services and parameters:
Cannot resolve parameter 'MyProj.Engine.Services.Interfaces.IAccountService accountService' of constructor 'Void .ctor(MyProj.Engine.Services.Interfaces.IAccountService)'.
Fixed myself. Actually the issue was that project is Azure Mobile Service.
It was my first experience with it and I have configured it as I used to do for WebApi. But as I understood after last googling this project type base on OWIN.
That's good article about: http://blogs.msdn.com/b/azuremobile/archive/2014/04/19/autofac-and-azure-mobile-services-net-backend.aspx
So it should be like this:
ConfigOptions options = new ConfigOptions();
ConfigBuilder builder = new ConfigBuilder(options, (httpConfig, autofac) =>
{
autofac.RegisterInstance(new MyService()).As<IMyService>();
});
HttpConfiguration config = ServiceConfig.Initialize(builder);

Simple injector webapi authorization attribute

I'm trying to create a custom authorization-attribute for my WebApi project.
In this attribute I would like to inject an IAuthModule object. I have no clue how I could implement this. I've found some solutions on the web but I have not been successful with any of them.
This is what I have so far:
public void Configuration(IAppBuilder app)
{
// WebApi config
HttpConfiguration config = new HttpConfiguration();
// SimpleInjector
var container = new SimpleInjector.Container();
container.Register<IAuthModule, CoreAuthModule>();
container.RegisterWebApiFilterProvider(config);
container.RegisterWebApiControllers(config);
container.Verify();
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
// Setup Oauth
ConfigureOAuth(app, container.GetInstance<IAuthModule>());
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
and the attribute:
public class CustomAuthorizationAttribute : AuthorizeAttribute
{
// how can I inject something here?
public IAuthModule AuthModule { get; set; }
protected override bool IsAuthorized(HttpActionContext actionContext)
{
return false;
}
}
The Simple Injector Web API integration guide goes into more details about this in the Injecting dependencies into Web API filter attributes section. What it basically describes is that you need to do two things:
Use the RegisterWebApiFilterProvider extension method to allow Simple Injector to build-up Web API attributes.
Register a custom IPropertySelectionBehavior to make sure Simple Injector will inject dependencies into your attribute's properties.
So this basically comes down to adding the following registration:
var container = new Container();
container.Options.PropertySelectionBehavior = new ImportPropertySelectionBehavior();
container.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
Where the ImportPropertySelectionBehavior is implemented as follows:
using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Reflection;
using SimpleInjector.Advanced;
class ImportPropertySelectionBehavior : IPropertySelectionBehavior {
public bool SelectProperty(Type type, PropertyInfo prop) {
return prop.GetCustomAttributes(typeof(ImportAttribute)).Any();
}
}
This custom IPropertySelectionBehavior enables explicit property injection where properties are marked with the System.ComponentModel.Composition.ImportAttribute attribute. Any property that is marked with this attribute will get injected.
Do note that dependency injection in attributes is sub optimal as described here and here.

Hook Unity into Web API Filter Attributes

I have Unity running great for all the controllers in my ASP.NET Web API project - just using the default set up that comes out of the NuGet box. I have also managed to hook it up to MVC Filter Attributes - but can't seem to do the same for ASP.NET Web API filter attributes.
How to I extend this default implementation to inject a dependency into an ActionFilterAttribute, for example...
public class BasicAuthenticationAttribute : ActionFilterAttribute
{
[Dependency]
public IMyService myService { get; set; }
public BasicAuthenticationAttribute()
{
}
}
This filter is applied to controllers using attributes:
[BasicAuthentication]
I'm pretty sure I need to hook up the Unity container so it handles the creation of the attribute class, but need some clues about where to start as it does not use the same extensibility points as the MVC filters.
I just wanted to add, other things I have tried include service location rather than dependency injection, but the DependencyResolver you get back is not the same one you configure.
// null
var service = actionContext.Request.GetDependencyScope().GetService(typeof(IMyService));
Or
// null
var service = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IApiUserService));
The problem is that the Attribute class is created by .NET and not by the WebAPI framework.
Before reading farther, did you forget to configure your DependencyResolver with your IApiUserService?
(IUnityContainer)container;
container.RegisterType<IApiUserService, MyApiUserServiceImpl>();
...
var service = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IApiUserService));
I created an App_Start\UnityConfig class that holds my UnityContainer:
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
public static void Configure(HttpConfiguration config) {
config.DependencyResolver = new UnityDependencyResolver(UnityConfig.GetConfiguredContainer());
}
/// <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>
private 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>();
container.RegisterType<MyClass>(new PerRequestLifetimeManager(), new InjectionConstructor("connectionStringName"));
}
}
The UnityDependencyResolver and PerRequestLifetimeManager came from this blog post and Unity.WebApi (Project/Nuget Package) which I internalized. (since it's a bootstrap)
When I need to make use of the UnityContainer in my other code, I passed it into the constructor:
config.Filters.Add(new MyFilterAttribute(UnityConfig.GetConfiguredContainer()));

Resources