I'm using Simple Injector with an ASP.NET Web API project, and I want to use different implementations for one interface, depending on the version of REST endpoint used. For example, if v1 of an endpoint is used, IPaymentData should be instantiated with a class called PaymentData, but if v2 is used IPaymentData should be implemented by a class called PaymentDataNew. This is turning out to be problematic!
I don't want to use a composite class like a part of Simple Injector documentation suggests since that means that my code needs to be aware of and take into account the injection framework I'm using (bad).
I noticed in the latest version (3.0) that something called "Context based injection" is a feature. Using the container.RegisterConditional function it should be possible to run a delegate each time a type is resolved.
container.RegisterConditional(typeof(IPaymentData),
c => ((HttpContext.Current.Items["version"] as string ?? "1") == "2")
? typeof(PaymentDataNew)
: typeof(PaymentData),
Lifestyle.Scoped,
c => true);
This doesn't seem to work, though, since even though the lifetime is scoped, and the default lifestyle is WebApiRequestLifestyle the delegate which returns the implementation depending on version is only called for the first request that comes in. Subsequent requests skip this (they seem to be using a cached implementation).
Is there something I'm missing? How can I make sure the delegate is called each time a request comes in??
since that means that my code needs to be aware of and take into account the injection framework I'm using
Not exactly. The composite pattern is a well known and commonly used pattern, so defining it in your code doesn't make your code dependent on the DI library. And if you don't want to define the composite in your application code, you can always specify it inside your Composition Root. The Composition Root already has a very strong dependency on the DI library, so any library-specific stuff should be placed there.
Using the container.RegisterConditional function it should be possible to run a delegate each time a type is resolved.
Simple Injector v3's RegisterConditional method allows applying registrations conditionally based on static information. This means that the supplied predicate is only called a finite amount of time (usually once per consuming component). The methods (IntelliSense/XML) documentation states:
The predicate will only be evaluated a finite number of times; the predicate is unsuited for making decisions based on runtime conditions.
It will not be called every time you resolve it. The reason for this is two-fold:
This optimizes performance, because the decision made in the predicate can be burned into the compiled expression, but more importantly,
This prevents you from making runtime decisions during the building of the object graph.
The shape of your object graph should not be dependent on runtime parameters (such as the version in your HttpContext). Doing this complicates the object graph and makes it very hard to verify and diagnose the object graph for correctness.
The solution I would advice is to implement a proxy implementation for IPaymentData that allows making the switch at runtime. This is not a Simple Injector specific implementation; you should strive to have simple, static, and verifiable object graphs, independently of the DI library you use.
This is how such proxy might look like:
public sealed class HttpRequestVersionSelectorPaymentData : IPaymentData
{
private readonly PaymentData paymentOld;
private readonly PaymentDataNew paymentNew;
public VersionSelectorPaymentData(PaymentData old, PaymentDataNew paymentNew) { ... }
private bool New => HttpContext.Current.Items["version"] as string ?? "1") == "2";
private IPaymentData PaymentData => this.New ? paymentNew : paymentOld;
// IPaymentData method(s)
public Payment GetData(int id) => this.PaymentData.GetData(id);
}
Although it is absolutely possible to make runtime decisions during the building of the object graph (by registering a delegate), I strongly advice against doing this, for the reasons expressed above.
Related
I'm migrating a tool to a .net 5 console app. I would like to change my DI system, currently a modified version of TinyIoC, to use if possible the built-in DI. Currently, my tool will load and auto-register any dll it finds in its config file. First-in wins, so a user-provided implementation of one of my interfaces will take precedence over my default one, loaded last.
Additionally, I need to be able to register several variants of a given interface, and have my DI system choose between them based on configuration. Currently, this works with a RegistrationName attribute that I've added to Tiny. When tiny auto-registers everything in a dll, it includes this name in it's registration.
So, for example, I have a IProvider interface, with methods including IDbConnection GetConnection(string connectionString);. I have several default implementations for SQL Server, Postgres, etc. and users can provide other implementations in dlls that I don't know about when compiling my tool.
Here is how I declare my SQL Server provider...
[RegistrationName("System.Data.SqlClient")]
class SqlClient : IProvider
{
Here is how I specify provider in my qfconfig.json...
{
"defaultConnection": "Data Source=localhost;Initial Catalog=Northwind;Integrated Security=True",
"provider": "System.Data.SqlClient"
}
Here is how I ask Tiny for a concrete instance...
// RegistrationName is passed to the Resolve method.
// Tiny returns the implementation whose RegistrationName matches.
_provider = _tiny.Resolve<IProvider>(config.provider);
So I want to keep this possibility, but find a less personal way of doing it.
I fear I've strayed out into the forest on this subject. The docs and tutos that I find all cover much simpler scenarios, where there's one registered implementation of an interface, and everything is explicitly registered in code. Can someone point me back on the road please?
If I understand your use case correctly, you have possible multiple IProvider implementations, but always only need one at runtime, which is based on the the configured value that maps to the RegistrationName attribute.
There's nothing built-in to the MS.DI framework that simplifies such use case, but as you only need to register one at runtime, you can achieve this by iterating the assemblies and finding that specific implementation and register that:
var providers =
from assembly in assemblies
from type in assembly.GetExportedTypes()
where typeof(IProvider).IsAssignableFrom(type)
where !type.IsAbstract
let attr = type.GetCustomAttribute<RegistrationNameAttribute>()
where attr?.Name == config.provider
select type;
services.AddTransient(typeof(IProvider), providers.Single());
This way registration is based on the name, while resolving can be done in a keyless fashion:
serviceProvider.GetRequiredService<IProvider>();
In the case I misunderstood your question, and you need multiple IProvider implementations at runtime, and need to resolve them by their key... well, that's certainly possible, but you will have to write more code. And here's the takeaway from everything that follows, ActivatorUtilities is your friend:
// Find all 'name -> provider' mappings
var providerDefinitions =
from assembly in assemblies
from type in assembly.GetExportedTypes()
where typeof(IProvider).IsAssignableFrom(type)
where !type.IsAbstract
let name = type.GetCustomAttribute<RegistrationNameAttribute>()?.Name
where name != null
select new { name, type };
// Helper method that builds IProvider factory delegates
Func<IServiceProvider, IProvider> BuildProviderFactory(Type type) =>
provider => (IProvider)ActivatorUtilities.CreateInstance(provider, type);
// Create a dictionary that maps the name to a provider factory
Dictionary<string, Func<IServiceProvider, IProvider>> providerFactories =
providerDefinitions.ToDictionary(
keySelector: i => i.name,
elementSelector: i => BuildProviderFactory(i.type));
// Possible use
Func<IServiceProvider, IProvider> factory = providerFactories[config.provider];
IProvider provider = factory(serviceProvider);
ActivatorUtilities.CreateInstance is MS.DI's extension point that allows the creation of unregistered classes, while injecting them with dependencies that are part of the provided IServiceProvider instance.
ActivatorUtilities.CreateInstance comes with a lot of unfortunate subtle downsides, such as the inability to check for cyclic dependencies, which could lead to nasty stack overflow exceptions instead. But this is the best we can achieve with MS.DI. Other DI Containers are more mature and feature rich in this respect.
I have a scenario that i have a Client of webAPi that need base url in it's constructor and An configuration manager class that reads configuration from web.config.
interface IConfigManager
{
string baseurl {get;}
}
class ConfigManager:IConfigManager
{
public string baseurl => system.configuration.ConfigruationManager.AppSettings["URL"];
}
and i have a client class that calls the web api
interface IApiClient
{
List<Products> GetProducts(string addresssufix);
}
public class ApiClient:IApiClient
{
public ApiClient(string baseUrl)
{
//----
}
List<Products> GetProducts(string addresssufix)
{
//....
}
}
so i require Url in APiClient
in simple injector while registration of components.
container.Register<IConfigManager, ConfigManager>();
var config= container.GetInstance<IConfigManager>();
container.Register<IApiClient<(()=> new ApiClient(config.baseurl));
but it said i can't register after calling GetInstance
Simple Injector blocks any calls to Register after the first call to GetInstance to force strict registration between registration and resolve. This design prevents strange, hard to debug, and hard to verify behaviour as explained in more detail here in the documentation.
But just as you want to separate the registration phase from the phase where you start resolving from the container, you should do the same when reading configuration values. Configuration values should only be loaded at application start-up, before or during the time of the registration phase. Delaying the reading of configuration values causes applications to become brittle and forces you to go through the complete application to find out whether or not the application is configured correctly, while this can easily be prevented by loading the configuration at start-up (and thus letting the application fail fast).
This means, that in your situation it doesn't make much sense to have an IConfigManager abstraction, since it's only goal is to delay the loading of base URL from the app settings, while again, this should be done directly at start-up (and should preferably fail in case that value is missing or malformed).
With that in mind, I would like to propose the following improvement and simplification to your design:
var container = new Container();
string baseUrl = System.Configuration.ConfigruationManager.AppSettings["URL"];
if (string.IsNullOrEmpty(baseUrl))
throw new ConfigurationErrorsException("appSettings/URL is missing.");
container.RegisterSingleton<IApiClient>(new ApiClient(baseUrl));
See how the configuration is read directly at startup and checked immediately whether the value exists. After that the baseUrl is used directly in the ApiClient constructor. Also note that ApiClient is registered as Singleton. I assume here that ApiClient is stateless and immutable (which is a good practice).
Note that you did the right thing by letting your ApiClient depend on the string baseUrl configuration value, instead of injecting the IConfigManager. Using ConfigManager as an abstraction in application code is typically problematic. Such configuration abstraction will typically grow indefinitely during the lifetime of the application, since every time a new configuration value is added to the configuration, this abstraction (and its implementation and possible fake implementations) need to be updated. Consumers of that abstraction will typically only depend on one or a few configuration values, but never on all. This is an indication of a Interface Segregation Principle violation. Problem with that is that it becomes harder to test consumers of that interface, because you typically want to be sure that they use the correct configuration values. Another problem is that from the definition of such a consumer (its type name and its constructor with required dependencies) it becomes impossible to see which configuration values are actually required.
All these problems go away completely when you let consumers depend directly on the configuration value they require. But again, this even removes the need to have this IConfigManager abstraction in the first place.
Do note that although register-resolve-register is not permitted, you would be able to do the following instead:
container.Register<IConfigManager, ConfigManager>();
container.Register<IApiClient>(() =>
new ApiClient(container.GetInstance<IConfigManager>().baseurl));
What is going on here is that GetInstance<IConfigManager> is called as part of the delegate for IApiClient. This will work because in that case the GetInstance<IConfigManager>() is called while resolving the IApiClient and thus after the registration process. In other words, resolving IConfigManager is delayed.
Big warning about this though: This practice is typically not advised. As explained before, when it comes to configuration values, we don't want to load them lazily. But even in other cases, we typically don't want to do this, because this construct blinds Simple Injector's verification and diagnostic system. Since Simple Injector uses statically available information (such as constructor arguments) to analyse your object graphs, such dynamic call will disallow Simple Injector to find common problems such as Lifestyle Mismatches. In other words, this construct should only be used in rare cases were you're sure that misconfigurations won't occur.
Pass the dependent object to ApiClient, instead of just a property of it. If that object has too many properties in which ApiClient is not interested, do interface segregation.
container.Register<IConfigManager, ConfigManager>();
container.Register<IApiClient, ApiClient>();
public ApiClient(IConfigManager configManager)
{
this.baseurl = configManager.baseurl;
}
container.GetInstance<ApiClient>();
We are building an application which has a number integration touch points with other systems. We are effectively using Unity for all our dependency injection needs. The whole business layer has been built with an interface driven approach, with the actual implementation being injected at an outer composition root during bootstrap of the application.
We wanted to handle the integration layer in an elegant manner. The business classes and repositories are dependent on IIntegrationController<A, B> interfaces. Several IIntegrationController<A, B> implementations together represent integration with one target system in the background - forming an integration layer. Currently, we hook up everything in the composition root, one shot, at the beginning. The consumers of this interface are also registered with an appropriate InjectionConstrutor and ResolvedParameter up front. Most types are operating with a PerResolveLifetime and the business classes consuming the IIntegrationController are also resolved for each request context separately.
Refer code below.
// IIntegrationController Family 1
// Currently the default registration for IIntegrationController types injected into the business classes
container.RegisterType<IIntegrationController<A, B>, Family1-IntegrationController<A, B>>();
container.RegisterType<IIntegrationController<C, D>, Family1-IntegrationController<C, D>>();
// IIntegrationController Family 2 (currently not registered)
// We want to be able to register this, or manage this set of mapping registrations separately from Family 1,
// and be able to hook these up dynamically instead of Family-1 on a per-resolve basis
container.RegisterType<IIntegrationController<A, B>, Family2-IntegrationController<A, B>>();
container.RegisterType<IIntegrationController<C, D>, Family2-IntegrationController<C, D>>();
// Repository/Business Class that consume IIntegrationControllers.
// There is a whole family of IIntegrationController classes being hooked in,
// and there are multiple implementations for the family (as shown above). A typical AbstractFactory scenario.
container.RegisterType(typeof(Repository<Z>), new PerResolveLifetimeManager(),
new InjectionConstructor(
new ResolvedParameter<IIntegrationController<A, B>>(),
new ResolvedParameter<IIntegrationController<C, D>>())
);
Problem Statement:
We want the ability to switch an entire family of IIntegrationController<A, B> at runtime. When the business class is being resolved, we want it to be injected with the right version of IIntegrationController<A, B>, based on a request parameter available in the context.
A "named" registration based solution would not be scalable, due to two reasons (an entire family of integration classes has to be switched, and it would require clunky name registrations and conditional resolution in the code making it hard to maintain).
The solution should work even when there is a chain/hierarchy of resolutions taking place, i.e. the direct consumer of the IIntegrationController is also resolved through Unity, as it is injected into another class dynamically.
We have tried a DependencyOverride and ResolveOverride class during resolution, but that would require the whole set of Family-2 IIntegrationController resolutions to be overriden, instead of just being able to switch the whole layer.
We understand that instead of injecting a IIntegrationController directly into the business class, an AbstractFactory may have to be injected, but we are not able to get that working, and are not sure where the registration and resolution would happen. If the business class is hooked with an AbstractFactory, first I would have to hook up the right factory per-resolve,
Does this require overriding the InjectionFactory? This link suggests an approach, but we were unable to get it to work smoothly.
What's nice about your design is that you already have the right abstractions in place. You use generic abstractions, so the problem can be solved simply by applying the right patterns on top of your already SOLID design.
In other words, use a proxy:
// This class should be considered part of your composition root.
internal class IntegrationControllerDispatcher<TRequest, TResult>
: IIntegrationController<TRequest, TResult>
{
private readonly IUserContext userContext;
private readonly Family1_IntegrationController<A, B> family1Controller;
private readonly Family2_IntegrationController<A, B> family2Controller;
public IntegrationControllerDispatcher(
IUserContext userContext,
Family1_IntegrationController<A, B> family1Controller,
Family2_IntegrationController<A, B> family2Controller) {
this.userContext = userContext;
this.family1Controller = family1Controller;
this.family2Controller = family2Controller;
}
public TResult Handle(TRequest request) {
return this.GetController().Handle(request);
}
private IIntegrationController<TRequest, TResult> GetController() {
return this.userContext.IsInFamily("family1"))
? this.family1Controller
: this.family2Controller;
}
}
With this class you whole configuration can be reduced to about this:
container.RegisterType<IUserContext, AspNetUserContext>();
container.RegisterType(
typeof(IIntegrationController<,>),
typeof(IntegrationControllerDispatcher<,>));
container.RegisterType(typeof(Repository<>), typeof(Repository<>));
Note the following:
Note the use of the registrations that do an open-generic mapping. You don't have to register ALL your closed versions one by one. You can do it with one line of code.
Also note that the types for the different families aren't
registered. Unity can resolve them automatically, because our
IntegrationControllerDispatcher depends on them directly. This
class is a piece of infrastructure logic and should be placed inside
your Composition Root.
Note that the decision to use a specific family implementation is not made during the time that the object graph is built; It is made at runtime, because the value that determines this is a runtime value. Trying to determine this at the time the object graph is built, will only complicate things, and make it much harder to verify your object graphs.
Furthermore, this runtime value is abstracted behind a function call and placed behind an abstraction (IUserContext.IsInFamily in this case, but that's just an example of course).
I am attempting to use Ninject on my current project, and up to now, have been loving it. I am in the middle of attempting to configure an IInterceptor object to intercept and handle a failed method call to my service layer. This is hosted in an ASP.NET MVC 5 application.
In the IInterceptor, I've tried several things, such as:
Setting private variables using constructor injection, but came to discover that it appears Ninject will reuse an IInterceptor instance for a method indefinitely, and I haven't found a way to stop that. Since one of the things I bring into scope is a DbContext which gets disposed elsewhere, it ends up failing on any future requests than the one it was created on.
I found that the IInvocation has a Request.Kernel property. However, when I attempt to resolve my UOW from the container, which is .InRequestScope(), it fails, since it attempts to resolve the IUowService dependencies, (one of the dependencies depends on the HttpContext which is null at this point), but appears to be doing so outside the Request scope. It is ignoring the fact that the dependencies it needs have already been created within the ASP.NET request, and is attempting to create new ones.
Setting a binding for the interceptor this.Bind<NinjectExceptionHandler>().ToSelf().InTransientScope(), yet this didn't seem to stop the caching of the interceptor.
I imagine there is something I am missing. I understand wanting to cache IInterceptor objects for performance, but I find it irksome that I can't easily use the IOC container or Injection to get the objects I need for my request.
This is the last issue I am having with getting interception up and running as I need, so any help is greatly appreciated!
Per your request i'm going into more detail on how we've achieved "1 proxy : 1 interceptor" instance relation ship.
We've taken the easy way which does not offer as much flexibility as what the official ninject interception extensions offers. We are relying directly on castle.core dynamic proxy and thus castle's IInvocation interface.
(Please not the code below is for a proxy without target, but a proxy with target is quite similar -- the only thing which changes is that you'll need to know the target class type and use IResolutionRoot.Get<TargetClassType>() to instanciate it).
Basically we created a binding like:
IBindingRoot.Bind<IFoo>()
.ToProvider<InterfaceProxyWithoutTargetProvider<IFoo>>();
Now of course we need to know which interceptors the proxy shall use. Again we are using an easy - and not so nice - design:
public interface IInterceptorBindingDefinition<TTarget>
{
Type InterceptorType { get; }
}
public class InterceptorBindingDefinition<TTarget, TInterceptor> : IInterceptorBindingDefinition<TTarget>
where TInterceptor : IInterceptor
{
Type InterceptorType { get { return typeof(TInterceptor); } }
}
IBindingRoot
.Bind<IInterceptorBindingDefinition<IFoo>>()
.To<InterceptorBindingDefinition<TTarget, LoggingInterceptor>();
IBindingRoot
.Bind<IInterceptorBindingDefinition<IFoo>>()
.To<InterceptorBindingDefinition<TTarget, SomeOtherInterceptor>();
This means IFoo shall get two interceptors: LoggingInterceptor and SomeOtherInterceptor.
and the implementation of the provider:
public class InterfaceProxyWithoutTargetProvider<TInterface> : IProvider<TInterface>
where TInterface : class
{
private readonly IProxyGenerator proxyGenerator;
private readonly IInterceptorFactory interceptorFactory;
public InterfaceProxyWithoutTargetProvider(IProxyGenerator proxyGenerator, IInterceptorFactory interceptorFactory)
{
this.proxyGenerator = proxyGenerator;
this.interceptorFactory = interceptorFactory;
}
public Type Type
{
get { return typeof(TInterface); }
}
public object Create(IContext context)
{
var interceptorTypes = context.Kernel.Get<IEnumerable<IInterceptorBindingDefinition<TInterface>>();
IList<IInterceptor> interceptors = interceptorTypes
.Select(x => x.InterceptorType)
.Select(x => context.ContextPreservingGet(x))
.ToList();
return this.proxyGenerator.CreateInterfaceProxyWithoutTarget<TInterface>(interceptors);
}
}
Now of course we polished the thing a little bit so we have a fluent syntax configuring the binding of the proxy and the interceptor - which is easy enough.
However ninject.extensions.interception's approach with its IAdviceRegistry and IAdvice is certainly better (but also requires more insight into how ninject works).
So it appears that there is no way to do what I was trying gracefully with Ninject. Once in the IInterceptor and in the later parts of async operations, the HttpContext was lost and Ninject couldn't resolve things that really it should have thought were in scope. Coupled with the fact that it reused IInterceptor's for a method (like I said, understandable, but irritating), I just couldn't get it to work right as I wanted to.
What I was able to do to get around the fact was something simple, yet a little kludgy (I think). Since all the methods that I was intercepting were in my service layer, and all my services implemented a IBaseService through a BaseService abstract base class, which happened to have the objects I needed as properties, I was able to do this in the interceptor:
var uow = (invocation.Request.Target as IBaseService).UnitOfWork;
This allowed me to access my unit of work and Fail it, as well as access the logging instance I was working on.
While this works, I would like to see someway to get interceptor constructor injection working correctly through multiple calls, or calls to the Kernel further down the line to realize that it has already resolved an object still in scope (although I am guessing that it may think its out of scope since ASP.Net abandoned the scope upon await).
For any interested, I am going to try and post about this on my blog soon (see my user page if actually interested, not spamming SO myself).
I am using SimpleInjector as my IoC Container. I have created a Publish/Subscribe framework for which I now need to be able to refine by enabling subscribers to indicate their priority for execution. For example I could create a subscriber for preloading all of the data required for the remainder of a transaction.
One method I can think of is to create a [SubscriberPriority] attribute to indicate the requirement during the registration process RegisterManyForOpenGeneric but I haven't delved any deeper as yet.
Is there a way to manage the order that GetAllInstances returns registrations?
Update:
Another option I've just thought of would be to use CoC (Convention over Configuration) to order the instances as they are returned by GetAllInstances.
Since you're indicating that you are using GetAllInstances, I suspect that you use an RegisterManyForOpenGeneric overload that takes a callback delegate, as follows:
container.RegisterManyForOpenGeneric(
typeof(ISubstriber<>),
(type, impls) => container.RegisterAll(type, impls),
typeof(ISubstriber<>).Assembly);
In that case the order of which the list of implementations is supplied to the delegate depends on the order in which they are returned from the .NET metadata. RegisterManyForOpenGeneric simply calls GetExportedTypes() on the supplied assembly. The order in which these types are returned is highly unreliable and might in a future version of C# even change by recompiling the code and in a future version of the CLR just by restarting the application.
So if the implementations must be placed in the list in a certain order, all you have to to is to order the list of implementations:
(serviceType, impls) => container.RegisterAll(serviceType,
impls.OrderBy(type => [some condition]));
However, in general I would say that the order of things should not matter. If they do matter, take a good look at your design. There might be some issues here. For instance, the fact that you want to mark some classes with the [SubscriberPriority] attribute, indicates that you might be missing an abstraction. Perhaps you should give them their own interface and register them seperately.
Another thing that I would always advice to do is to hide the list of registrations from the application by placing them behind an composite:
public class CompositeSubscriber<T> : ISubscriber<T>
{
private IEnumerable<ISubscriber<T>> subscribers;
public CompositeSubscriber(
IEnumerable<ISubstriber<T>> subscribers)
{
this.subscribers = subscribers;
}
public void Handle(T value)
{
foreach (var subscriber in this.subscribers)
{
subscriber.Handle(value);
}
}
}
This composite can be registered as follows:
container.RegisterSingleOpenGeneric(typeof(ISubscriber<>),
typeof(CompositeSubscriber<>);
This case the application can simply depend on ISubscriber<T> instead of IEnumerable<ISubscriber<T>>. Instead of controlling the order using the callback of the RegisterManyForOpenGeneric method, now you can use the composite to control the order as well.