custom NET5 service factory with auto dispose features - c#

In .NET5/.NET6 we typically get our services from the ServiceProvider directly.
But in some cases this is not possible and we need to create a service factory. We inject the service factory into our services and then, within the service, the service factory creates instances on demand. A public example would be HttpClientFactory (for demonstrating the thought).
The usual use case would be if a service needs to have multiple instances of a service and the instances need to be (pre)configured within the using service.
My way to implement this looks as follows:
// appsettings.json
"MyServiceFactory": {
"Instances": {
"Instance1": {
"Option1": "Hi",
"Option2": "there"
},
"Instance2": {
"Option1": "Thanks",
"Option2": "for helping"
}
}
}
// the options class to bind
public class MyServiceFactoryOptions
{
public Dictionary<string, MyServiceOptions> Instances { get; set; } = new Dictionary<string, MyServiceOptions>();
}
// the factory implementation
public class MyServiceFactory : IMyServiceFactory
{
public readonly ILoggerFactory LoggerFactory;
public readonly ILogger<MyServiceFactory> Logger;
public readonly MyServiceFactoryOptions Options;
public MyServiceFactory(ILogger<MyServiceFactory> logger, IOptions<MyServiceFactoryOptions> options, ILoggerFactory loggerFactory)
{
LoggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
Options = options.Value;
}
public IMyService CreateInstance(string name)
{
if (Options.Instances.TryGetValue(name, out MyServiceOptions options))
{
ILogger<MyService> logger = LoggerFactory.CreateLogger<MyService>();
IOptions<MyService> iOptions = Microsoft.Extensions.Options.Options.Create(options);
return new MyService(logger, iOptions);
}
else
{
throw new Exception($"Config is missing instance configuration for {name}");
}
}
}
//the service registration
services
.AddOptions<MyServiceFactoryOptions>()
.BindConfiguration("MyServiceFactory");
services.TryAddTransient<MyServiceFactory>();
And the CreateInstance(string name) method actually works creating the instances with the given configuration as desired.
The problem rises when MyService needs to be disposed when the ASP.NET server is closed.
Typically
the (my) service implements IDisposable
the instance is created via the ServiceProvider
the instance is injected via the constructor
Dispose get's called when the server is shut down
In my implementation Dispose seems to be never called.
A hint why that my could be comes from Andrew Locks's arcticle - Four ways to dispose IDisposable.
As I understand it right now the problem is that the instances are not created via the ServiceProvider and therefor Dispose is not called.
Am I right and is there a way to get Dispose called?

Related

How to instantiate DbContext from IHostingService

I have a class that derives from BackgroundService (IHostedService) for running background tasks. This will be added to my services using builder.Services.AddHostedService<BackgroundTaskService>()
BackgroundService's task runs for the entire duration of the web application, checking for queued data to process.
My question is, how do I instantiate an instance of DbContext from this code?
I could have the BackgroundTaskService constructor accept a DbContext. But wouldn't that keep the DbContext open forever?
And how else could I instantiate it without duplicating all the code to scan my settings file for the connection string, etc.?
The recemmended approach is to inject IDbContextFactory<TContext> as described in the following article: Using a DbContext factory (e.g. for Blazor)
Some application types (e.g. ASP.NET Core Blazor) use dependency injection but do not create a service scope that aligns with the desired DbContext lifetime. Even where such an alignment does exist, the application may need to perform multiple units-of-work within this scope. For example, multiple units-of-work within a single HTTP request.
In these cases, AddDbContextFactory can be used to register a factory for creation of DbContext instances.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<ApplicationDbContext>(
options =>
options.UseSqlServer(#"Server=(localdb)\mssqllocaldb;Database=Test"));
}
Then in your controller:
private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;
public MyController(IDbContextFactory<ApplicationDbContext> contextFactory)
{
_contextFactory = contextFactory;
}
public void DoSomething()
{
using (var context = _contextFactory.CreateDbContext())
{
// ...
}
}
You can use scope service factory. Check here for reference.
Here you have an example:
// Injection
public class DataApi : BackgroundService
{
private readonly ILogger<DataApi> logger;
private readonly IServiceScopeFactory scopeFactory;
public DataApi(ILogger<DataApi> _logger, IConfiguration _cfg, IServiceScopeFactory _sSF)
{
logger = _logger;
scopeFactory = _sSF;
// e.g. data from appsettings.json
// var recovery = _cfg["Api:Recovery"];
}
// ...
// Usage
protected async Task DataCollector()
{
logger.LogInformation("Collector");
using (var scope = scopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<MyDbContext>();
var myList = await db.MyEntity
.AsNoTracking()
.Where(t => t.active)
.ToListAsync();
if (myList.Count == 0)
{
logger.LogInformation("Empty...");
return;
}
// logic...
}
await Task.CompletedTask;
}

Dependency Injection and Service Lifetimes [duplicate]

In my Asp.Net Core App I need a singleton service that I can reuse for the lifetime of the application. To construct it, I need a DbContext (from the EF Core), but it is a scoped service and not thread safe.
Therefore I am using the following pattern to construct my singleton service. It looks kinda hacky, therefore I was wondering whether this is an acceptable approach and won't lead to any problems?
services.AddScoped<IPersistedConfigurationDbContext, PersistedConfigurationDbContext>();
services.AddSingleton<IPersistedConfigurationService>(s =>
{
ConfigModel currentConfig;
using (var scope = s.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<IPersistedConfigurationDbContext>();
currentConfig = dbContext.retrieveConfig();
}
return new PersistedConfigurationService(currentConfig);
});
...
public class ConfigModel
{
string configParam { get; set; }
}
What you're doing is not good and can definitely lead to issues. Since this is being done in the service registration, the scoped service is going to be retrieve once when your singleton is first injected. In other words, this code here is only going to run once for the lifetime of the service you're registering, which since it's a singleton, means it's only going to happen once, period. Additionally, the context you're injecting here only exists within the scope you've created, which goes away as soon as the using statement closes. As such, by the time you actually try to use the context in your singleton, it will have been disposed, and you'll get an ObjectDisposedException.
If you need to use a scoped service inside a singleton, then you need to inject IServiceProvider into the singleton. Then, you need to create a scope and pull out your context when you need to use it, and this will need to be done every time you need to use it. For example:
public class PersistedConfigurationService : IPersistedConfigurationService
{
private readonly IServiceProvider _serviceProvider;
public PersistedConfigurationService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public async Task Foo()
{
using (var scope = _serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<IPersistedConfigurationDbContext>();
// do something with context
}
}
}
Just to emphasize, again, you will need to do this in each method that needs to utilize the scoped service (your context). You cannot persist this to an ivar or something. If you're put off by the code, you should be, as this is an antipattern. If you must get a scoped service in a singleton, you have no choice, but more often than not, this is a sign of bad design. If a service needs to use scoped services, it should almost invariably be scoped itself, not singleton. There's only a few cases where you truly need a singleton lifetime, and those mostly revolve around dealing with semaphores or other state that needs to be persisted throughout the life of the application. Unless there's a very good reason to make your service a singleton, you should opt for scoped in all cases; scoped should be the default lifetime unless you have a reason to do otherwise.
Although Dependency injection: Service lifetimes documentation in ASP.NET Core says:
It's dangerous to resolve a scoped service from a singleton. It may cause the service to have incorrect state when processing subsequent requests.
But in your case this is not the issue. Actually you are not resolving the scoped service from singleton. Its just getting an instance of scoped service from singleton whenever it requires. So your code should work properly without any disposed context error!
But another potential solution can be using IHostedService. Here is the details about it:
Consuming a scoped service in a background task (IHostedService)
Looking at the name of this service - I think what you need is a custom configuration provider that loads configuration from database at startup (once only). Why don't you do something like following instead? It is a better design, more of a framework compliant approach and also something that you can build as a shared library that other people can also benefit from (or you can benefit from in multiple projects).
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureAppConfiguration((context, config) =>
{
var builtConfig = config.Build();
var persistentConfigBuilder = new ConfigurationBuilder();
var connectionString = builtConfig["ConnectionString"];
persistentStorageBuilder.AddPersistentConfig(connectionString);
var persistentConfig = persistentConfigBuilder.Build();
config.AddConfiguration(persistentConfig);
});
}
Here - AddPersistentConfig is an extension method built as a library that looks like this.
public static class ConfigurationBuilderExtensions
{
public static IConfigurationBuilder AddPersistentConfig(this IConfigurationBuilder configurationBuilder, string connectionString)
{
return configurationBuilder.Add(new PersistentConfigurationSource(connectionString));
}
}
class PersistentConfigurationSource : IConfigurationSource
{
public string ConnectionString { get; set; }
public PersistentConfigurationSource(string connectionString)
{
ConnectionString = connectionString;
}
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new PersistentConfigurationProvider(new DbContext(ConnectionString));
}
}
class PersistentConfigurationProvider : ConfigurationProvider
{
private readonly DbContext _context;
public PersistentConfigurationProvider(DbContext context)
{
_context = context;
}
public override void Load()
{
// Using _dbContext
// Load Configuration as valuesFromDb
// Set Data
// Data = valuesFromDb.ToDictionary<string, string>...
}
}

How to use DI in WPF to having a new istance without ask to container

i'm trying to develop from scratch a WPF app with the use of Simpleinjector as a IOC container.
I'm new on this topic and i have some issue regards lifetime of object and hot use them correctly.
I started the app by following the WPF integration guide on simpleinjector manual.
But i don't understand how to receive a new instance every time a service needed it
As i ask in my previous post i need to receive a new unitOfWork every time a service need it.
as #Steven say on my previous post
Do note that transient means "allways a new instance is resolved when it is requested from the container." If you're not requesting it again, you will be operating on the same instance, which might explain the ObjectDisposedException.
In the other post i found a solutin but i think it's a little bit over-complicated and it's to create a factory and inject this instead of the instance because i want to call the container.getInstance only on the startup method and not on the service by passing the container as a dependency
It's the only way i have to achieve this or there is something that i don't understand on how to develop in DI way?
Example of code:
public class HeaderViewModelFactory : IWpfRadDispenserViewModelFactory<HeaderviewModel>
{
private readonly ProductionService _service;
public HeaderViewModelFactory(ProductionService service)
{
_service = service;
}
public HeaderviewModel CreateViewModel()
{
return new HeaderviewModel(_service);
}
}
public class HeaderviewModel : ViewModelBase
{
private readonly ProductionService _service;
public HeaderviewModel(ProductionService service)
{
_service = service;
CreateData();
}
private void CreateData()
{
_service.CreateTestCycle();
}
}
public class CycleService : GenericDataService<Cycle>
{
private readonly IUnitOfWork<WpfRadDispenserDbContext> _uowContext;
public CycleService(IUnitOfWork<WpfRadDispenserDbContext> uowContext)
: base(uowContext)
{
_uowContext = uowContext;
}
public void CreateTestCycle()
{
var cycleDataService = new GenericDataService<Cycle>(_uowContext);
var vialDataService = new GenericDataService<Vial>(_uowContext);
Cycle c = new Cycle();
c.BatchName = "test";
Vial v = new Vial();
v.Name = "Test Vial";
c.Vials.Add(v);
_uowContext.CreateTransaction(IsolationLevel.ReadCommitted);
try
{
vialDataService.Create(v);
_uowContext.Persist();
var list = vialDataService.GetAll();
cycleDataService.Create(c);
_uowContext.Persist();
_uowContext.Commit();
}
catch (Exception e)
{
Console.WriteLine(e);
_uowContext.RollBack();
throw;
}
finally
{
_uowContext.Dispose();
}
}
}
private static Container Bootstrap()
{
// Create the container as usual.
var container = new Container();
// Register your types:
// Register your windows and view models:
container.Register<WpfRadDispenserDbContextFactory>(Lifestyle.Transient);
container.Register<IUnitOfWork<WpfRadDispenserDbContext>,WpfRadDispenserUOW>();
container.Register(typeof(CycleService));
container.Register<IWpfRadDispenserViewModelFactory<ProductionViewModel>,
ProductionViewModelFactory>(Lifestyle.Transient);
container.Register<IWpfRadDispenserViewModelFactory<AnagraphicViewModel>,
AnagraphicsViewModelFactory>(Lifestyle.Transient);
container.Register<IWpfRadDispenserViewModelFactory<HeaderviewModel>,
HeaderViewModelFactory>(Lifestyle.Transient);
container.Register<IViewModelAbstractFactory,
ViewModelAbstractFactory>(Lifestyle.Transient);
container.Register<INavigator, Navigator>(Lifestyle.Transient);
container.Register<MainWindowViewModel>();
container.Register<MainWindow>();
//container.Options.EnableAutoVerification = false;
//container.Verify();
return container;
}
in this way every time i create a new viewmodel i receive the same service and ovviously the dbcontext it's not present anymore because disposed.
This is not the rela code but only an example that i made to understand how DI works.
Using Abstract Factory pattern is the most common and recommended approach. Using the container in your application directly is widely considered an anti-pattern, like the Service Locator (Service Locator is an Anti-Pattern) for a very good reason.
Abstract factory allows instantiation of objects without introducing a tight coupling to the actual implementation that knows how to create specific instances.
Most IoC frameworks support this pattern natively. Most of the time they provide the generic interface for the factory. You register the instance (the product) with the container and the framework will export a ready-to use factory for you. You add the dependency to this framework interface to your object e.g. constructor. Then you register the generic factory interface. The framework will automatically create the instance of the factory and inject it into the relevant instances e.g., via constructor.
I am not too familiar with Simple Injector, but the framework really keeps things simple. There is no such code generation.
But the pattern is very simple (that's why this is so easy to automate) and in no way complicated.
Example
The interface required to dynamically create the instances of type TInstance:
interface IFactory<TInstance>
{
TInstance Create();
}
The implementation of this factory:
class SaveItemFactory : IFactory<ISaveItem>
{
ISaveItem Create() => new SaveItem();
}
The type that needs to create a dependency dynamically:
interface IItemManager {}
class ItemManager : IItemManager
{
IFactory<ISaveItem> SaveItemFactory { get; }
public ItemManager(IFactory<ISaveItem> itemFactory) => this.SaveItemFactory = itemFactory;
public void SaveData(object data)
{
ISaveItem saveItem = this.SaveItemFactory.Create();
saveItem.SetData(data);
}
}
Configure the container:
public void Run()
{
var container = new SimpleInjector.Container();
container.Register<IFactory<ISaveItem>, SaveItemFactory>(Lifestyle.Singleton);
container.Register<IItemManager, ItemManager>(Lifestyle.Singleton);
IItemManager itemManager = container.GetInstance<IItemManager>();
itemManager.SaveData("Some Data");
}

Create scope using IServiceProvider from singleton instance

Let's say I have my own class QueueListener<TService, TPayload> inherited from BackgroundService. It opens TCP connection and listens incoming messages. On each message I would like to initialize service of TService type and pass deserialized from JSON instance of TPayload to it. TService is going to be registered as Transient, so it means to be lightweight and stateless as a handler for payload have to be (in my current task). For this purpose I am going to inject IServiceProvider in constructor of my QueueListener and create a scope on each message it receives. Does it sounds like a plan or am I overengineering? I want to avoid TService is singleton as well.
Documentation says:
It's dangerous to resolve a scoped service from a singleton. It may cause the service to have incorrect state when processing subsequent requests.
But I am not completely sure what does it means. There is no way to inject scoped service in BackgroundService because it has Singleton lifetime. Do they warn me to stop doing things like I do?
UPD #1
I explain why I suppose to create scope on each message. The idea behind that is to prevent listener to be blocked by message processing and to provide other developers possibility to create their own handlers and do some stuff on received message. Other developers can create database connections for instance while processing and I want it to be closed and released when handling is done.
Register TService as scoped and create a new scope per message. Then resolve TService from created scope. Just read Consuming a scoped service in a background task
You can write it like this:
services.AddHostedService<MyBackgroundService>();
services.AddScoped<IScopedServicePerMessage, ScopedServicePerMessage>();
...
public class MyBackgroundService : BackgroundService
{
private readonly IServiceProvider _sp;
public MyBackgroundService(IServiceProvider sp)
{
_sp = sp;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
DoWork(stoppingToken);
return Task.CompletedTask;
}
private void DoWork(CancellationToken stoppingToken)
{
while(true)
{
var msg = GetNextMessage();
using (var scope = _sp.CreateScope())
{
var servicePerMessage = scope.ServiceProvider.GetRequiredService<IScopedServicePerMessage>();
servicePerMessage.Handle(msg);
}
}
}
...
}
Regarding this:
It's dangerous to resolve a scoped service from a singleton. It may
cause the service to have incorrect state when processing subsequent requests.
It's about the case when you inject scoped service (ef core dbcontext, for instance) directly into singleton. It's not your case.
The documentation is referring to injecting a scoped service into a singleton service. Since the injection happens at the construction of the singleton object, the scoped service would be provided at that time. This will effectively increase the lifetime of the scoped service to that of a singleton service. This is dangerous because a scoped service lifetime is often chosen explicitly to ensure that the object gets disposed quickly again.
The most common example would be a database context which owns a database connection; you want to make sure that you free up this database connection as soon as possible to free up the resources. But if you injected the context into a singleton service, it would never get disposed.
That however does not mean that there is no way to consume scoped services within a singleton service. This is done by having the singleton service create a service scope from which it can then retrieve singleton services. It’s important though that this service scope is supposed to be short-lived. So take the example from ASP.NET Core itself, where a service scope is created for every request, and do something similar. For example in your case, you could do it for every incoming message if that makes sense for your application.
To create a service scope, you should inject an IServiceScopeFactory; you can then create a scope with it like this:
public async Task Process(TPayload payload)
{
using (var scope = _serviceScopeFactory.CreateScope())
{
var service = scope.GetService<TService>();
await service.Process(payload);
}
}
This pattern is strictly only necessary if you need to consume scoped services. You could resolve all other services directly without creating a scope. If you can reuse the same service instance to process all payloads, you could also inject the service as a singleton (same as registering it as transient but resolving it only once). If you need a fresh instance for every payload, then consider creating a scope even if it isn’t strictly necessary.
First, transient services are not scoped services. Transient services are usually externally owned by your code and are created each time they are resolved from the container. Container does not cache transient services.
TService is going to be registered as Transient ... For this purpose I am going to inject IServiceProvider in constructor of my QueueListener and create a scope on each message it receives.
You do not need a scope for resolving transient services. Even if you create a scope, the scope still does not manage / own transient services. That, for example, ending the lifetime of the scope does not end lifetime of transient services.
You could simply use the IServiceProvider injected in QueueListener to resolve TService. And each TService resolved should be already like what you want
lightweight and stateless as a handler for payload
With regards to
Documentation says:
What the document says might not be relevant now since you are not using scoped services. But in case you want to know the reason:
It's dangerous to resolve a scoped service from a singleton.
Singleton is a special kind of scope. Singleton services are created and cached within a "root" scope of the container, which is essentially the container itself.
If you resolve scoped service from singleton, the lifetime / scope where the service instance is resolved and cached is likely to be the "root" scope. This leads to a problem where the scoped service instance being cached inside the container, and shared across multiple client requests.
This is dangerous, because scoped services are supposed to be
Scoped lifetime services (AddScoped) are created once per client request (connection).
I don't wanted my singleton class depending on the IServiceProvider directly.
So I've used a custom factory to accomplish this goal.
May this code example help others:
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IScopedBar, ScopedBar>();
services.AddSingleton<IScopedServiceFactory<IScopedBar>, ScopedServiceFactory<IScopedBar>>(
(provider) => {
var scope = provider.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<IScopedBar>();
return new ScopedServiceFactory<IScopedBar>(() => new ScopedService<IScopedBar>(scope, service));
});
services.AddSingleton<ISingletonFoo, SingletonFoo>();
}
// ...
}
public interface ISingletonFoo
{
void DoSomethingUsingScopedServices();
}
public class SingletonFoo : ISingletonFoo
{
private readonly IScopedServiceFactory<IScopedBar> _barFactory;
public SingletonFoo(IScopedServiceFactory<IScopedBar> barFactory)
{
_barFactory = barFactory;
}
public void DoSomethingUsingScopedServices()
{
using var scopedService = _barFactory.CreateService();
scopedService.Service.DoSomething();
}
}
public interface IScopedBar
{
void DoSomething();
}
public class ScopedBar : IScopedBar
{
public void DoSomething()
{
// Do something
}
}
public interface IScopedService<T> : IDisposable
{
T Service { get; }
}
public interface IScopedServiceFactory<T>
{
IScopedService<T> CreateService();
}
public class ScopedService<T> : IScopedService<T>
{
private readonly IDisposable _scope;
public ScopedService(IDisposable scope, T service)
{
_scope = scope;
Service = service;
}
public T Service { get; }
public void Dispose()
{
_scope.Dispose();
}
}
public class ScopedServiceFactory<T> : IScopedServiceFactory<T>
{
private readonly Func<IScopedService<T>> _serviceFactory;
public ScopedServiceFactory(Func<IScopedService<T>> serviceFactory)
{
_serviceFactory = serviceFactory;
}
public IScopedService<T> CreateService()
{
return _serviceFactory();
}
}
Here is my code to consume scoped service:
public interface IScopedResolver<T> where T: class
{
TResult Resolve<TResult>(Func<T, TResult> dataFactory);
Task<TResult> ResolveAsync<TResult>(Func<T, Task<TResult>> dataFactory);
}
Implement class:
public class ScopedResolver<T> : IScopeResolver<T> where T: class
{
private readonly IServiceProvider _provider;
public ScopedResolver(IServiceProvider provider)
{
_provider = provider;
}
public TResult Resolve<TResult>(Func<T, TResult> dataFactory)
{
using IServiceScope scope = _provider.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<T>();
return dataFactory(service);
}
public async Task<TResult> ResolveAsync<TResult>(Func<T, Task<TResult>> dataFactory)
{
using var scope = _provider.CreateScope();
var service = scope.ServiceProvider.GetRequiredService<T>();
return await dataFactory(service);
}
}
Register at startup:
services.AddSingleton(typeof(IScopedResolver<>), typeof(ScopedResolver<>));
using ScopedResolve:
public class ServiceA
{
private readonly IScopedResolver<DbContext> _context;
public ServiceA(IScopedResolver<DbContext> context)
{
_context = context;
}
public async Task<List<ClassOne>> GetListAsync()
{
return await _context.ResolveAsync(async s => await s.Set<ClassOne>().ToListAsync());
}
}

using a Handler in Web API and having Unity resolve per request

I am using Unity as my IoC framework and I am creating a type based on the value in the header of each request in a handler:
var container = new UnityContainer();
container.RegisterType<IFoo,Foo>(new InjectionConstructor(valuefromHeader));
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApi.UnityDependencyResolver(container);
The problem is that the handler's SendAsync means that the global container is getting overwritten by different requests and the controllers that use IFoo in their constructor are getting the wrong values.
1) Can I make the SendAsync sync?
2) If not, how do I create different instances for each request and have the IoC container resolve safely?
I have looked at the following articles without success:
http://www.asp.net/web-api/overview/extensibility/using-the-web-api-dependency-resolver
http://www.strathweb.com/2012/11/asp-net-web-api-and-dependencies-in-request-scope/
http://benfoster.io/blog/per-request-dependencies-in-aspnet-web-api-using-structuremap
Thanks in advance.
I agree with #Steven's approach, but that doesn't answer your more general question of how to resolve per request.
I would recommend you change to using the UnityHierarchicalDependencyResolver and then anything you register with HierarchicalLifetimeManager will be resolved per request.
Change this...
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApi.UnityDependencyResolver(container);
to this...
GlobalConfiguration.Configuration.DependencyResolver =
new Unity.WebApi.UnityHierarchicalDependencyResolver(container);
The problem you are having is caused by you mixing runtime values with design time dependencies. In general, the services you resolve from the container should not depend on runtime values in their constructor. You shouldn't do this, because components tend to live much longer than runtime values and injecting runtime values into components, makes it much harder to diagnose and verify the container's configuration.
Instead, hide that value behind a service that can provide consumers with that instance when required. For instance:
public interface IHeaderValueProvider
{
HeaderValue GetCurrentValue();
}
You can create an implementation that can be easily registered and injected into any component that needs that value. Anytime after the construction phase, those components can call the GetCurrentValue() method on the injected IHeaderValueProvider dependency.
I managed to resolve per request by declaring my custom UnityResolver's class within the WebApiConfig class. The UnityResolver class uses the HttpConfiguration class assuming you're using an OWIN context.
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var _container = new UnityContainer();
DependencyConfiguration.ConfigureContainer(_container);
config.DependencyResolver = new UnityResolver(_container);
}
The ConfigureContainer class is simply a class where I declare my IOC dependencies as shown below:
private static void RegisterReleaseEnv(IUnityContainer container)
{
//Repository Registration
container
.RegisterType(typeof(IRepository<>), typeof(GenericRepository<>), new HierarchicalLifetimeManager());
}
It is very important that you use the HierarchicalLifetimeManager lifetime manager so that you get a new instance per request.
The UnityResolver class then looks like this:
public class UnityResolver : IDependencyResolver
{
protected IUnityContainer container;
public UnityResolver(IUnityContainer container)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
this.container = container;
}
public object GetService(Type serviceType)
{
try
{
return container.Resolve(serviceType);
}
catch (ResolutionFailedException)
{
return null;
}
}
public IEnumerable<object> GetServices(Type serviceType)
{
try
{
return container.ResolveAll(serviceType);
}
catch (ResolutionFailedException)
{
return new List<object>();
}
}
public IDependencyScope BeginScope()
{
var child = container.CreateChildContainer();
return new UnityResolver(child);
}
public void Dispose()
{
container.Dispose();
}
}
I hope this helps.
For more information: http://www.asp.net/web-api/overview/advanced/dependency-injection

Categories

Resources