Perhaps I am missing something or tried something improperly, but I thought I would reach out.
I have a singleton service that I want to create multiple times. The service has the same logic except for a configuration parameter. So I want to inject a parameter at runtime into the service constructor.
Is this possible, or will I have to do something more elaborate?
Thanks for your input.
For example…
// I am creating three different configurations
services.Configure<ProfileCacheOptions>(
ProfileCacheOptions.Key1,
config.GetSection(ProfileCacheOptions.Key1));
services.Configure<ProfileCacheOptions>(
ProfileCacheOptions.Key2,
config.GetSection(ProfileCacheOptions.Key2));
services.Configure<ProfileCacheOptions>(
ProfileCacheOptions.Key2,
config.GetSection(ProfileCacheOptions.Key3));
.
.
.
// I have tried multiple ways to inject a parameter, but as you can see
// my last attempt was a simple string representing the key
services.AddSingleton<ICachedDataSource<Class1>,
MemoryCacheData<Class1>>(ProfileCacheOptions.Key1);
services.AddSingleton<ICachedDataSource<Class2>,
MemoryCacheData<Class2>>(ProfileCacheOptions.Key2);
services.AddSingleton<ICachedDataSource<Class3>,
MemoryCacheData<Class3>>(ProfileCacheOptions.Key3);
// The proposed argument, whatever it may be
public MemoryCacheData(
IMemoryCache cache,
IOptionsSnapshot<CachedDataBaseClassOptions> options,
string TheArgument
{
_options = options.Get(TheArgument);
}
I have tried creating an argument class and multiple attempts to create a runtime injected parameter.
You can create an instance of the singleton before you add it to the DI container, like so:
var singleton1 = new MemoryCacheData<Class1>(ProfileCacheOptions.Key1);
services.AddSingleton(typeof(ICachedDataSource<Class1>), singleton1);
You have to provide a factory (or in this case a simple Func<>) that creates the desired instance at runtime. Something like this:
services.AddSingleton<ICachedDataSource<Class1>>(provider =>
{
// The provider is the running DI container and you can ask
// for any service as usual to retrieve dependencies
var cacheOptions = provider.GetRequiredService<ICachedDataSource<Class1>>();
var data = new MemoryCacheData<Class1>(cacheOptions);
return data;
});
I think it doesn't fully match your code, but hopefully you understand the approach and can use it.
Related
I was wondering whether Autofac allows me to grab information about the requesting context so I can modify my resulting service for the respective binding based on it.
For example something like this:
builder.Register(ctx =>
{
var name = ctx.Request.Name; // How do I do something like this?
return new MyService(name);
})
.As<IMyService>()
.SingleInstance();
public class MyClass
{
public MyClass(IMyService myService)
{
...
}
}
In this context, I would like to infer information about the calling context into a specific service (For e.g. logging purposes), but I didn't find any information on how Autofac would allow me to do such a thing. Basically, I would like to get a hold of the MyClass type in this case, but since I don't know upfront who might use the IMyService binding, I can't hardcode it.
Apparently Autofac does allow conditional binding, but the requesting side always has to provide metadata, so the flow is kind of turned the other way round.
I've used other IoC containers like Ninject before, and for Ninject it was simply included in one of the parameters of the lambda registration.
Is this possible?
I'm working with an existing Web Api that uses Simple Injector to register a single database connection. I need to make an endpoint to get info from a different db but I don't know how to register a new connection.
These are the existing registrations for the main db:
_container.Register<IDataBaseSqlServerDapper>(
() => new DataBaseSqlServerDapper(SqlServerDb.ConnectionString(),
LogManager.GetLogger("")));
_container.RegisterWebApiRequest<IDbConnectionFactory>(
() => new OrmLiteConnectionFactory(SqlServerDb.ConnectionString(),
new SqlServerOrmLiteDialectProvider()));
_container.RegisterWebApiRequest(
() => new PetaPoco.Database(Connection.SurveyEngine) {
IsolationLevel = IsolationLevel.Snapshot
});
So I read about RegisterCollection method and I tried the following:
_container.RegisterCollection<IDataBaseSqlServerDapper>(new[]
{
new DataBaseSqlServerDapper(SqlServerDb.ConnectionString(), LogManager.GetLogger("")),
new DataBaseSqlServerDapper(AdmbbDb.ConnectionString(), LogManager.GetLogger(""))
});
_container.RegisterCollection<IDbConnectionFactory>(new[]
{
new OrmLiteConnectionFactory(
SqlServerDb.ConnectionString(),
new SqlServerOrmLiteDialectProvider()),
new OrmLiteConnectionFactory(
AdmbbDb.ConnectionString(),
new SqlServerOrmLiteDialectProvider())
});
_container.RegisterCollection<PetaPoco.Database>(new[]
{
new PetaPoco.Database(Connection.SurveyEngine) {
IsolationLevel = IsolationLevel.Snapshot },
new PetaPoco.Database(Connection.Admbb) {
IsolationLevel = IsolationLevel.Snapshot }
});
SqlServerDb, AdmbbDd and Connection are classes that contains the names of the connection strings.
But I'm getting this error:
The configuration is invalid. Creating the instance for type IDapperQueryFactory failed. The constructor of type DapperQueryFactory contains the parameter with name 'dataBaseSqlServerDapper' and type IDataBaseSqlServerDapper that is not registered. Please ensure IDataBaseSqlServerDapper is registered, or change the constructor of DapperQueryFactory. There is, however, a registration for IEnumerable<IDataBaseSqlServerDapper>; Did you mean to depend on IEnumerable<IDataBaseSqlServerDapper>?
How can I solve this?
In the existing case you specify that type IDataBaseSqlServerDapper can be used for injection, which in turn gets properly injected into your object (in this case a class that implements IDapperQueryFactory).
In the second case you are registering multiple services of type IDataBaseSqlServerDapper. Meaning that your DI does not know how to resolve a single IDataBaseSqlServerDapper, only a collection of them.
This means that you'll either have to change the constructor to accept IEnumerable<IDataBaseSqlServerDapper> or register a non-collection IDataBaseSqlServerDapper
Simple Injector's documentation lists a good example how you can use both Register and Collection.Register side by side to get it working (source).
Now as for your problem, you state:
I need to make an endpoint to get info from a different db but I don't know how to register a new connection.
If you simply want to change where the data is going, can't you just replace the old existing handler?
If your goal is to load data from multiple datasources, you'll need to have some kind of logic that allows your code to determine which source it should use to store/load data.
The example from the simple injector documentation provides a good basis for something like this that does not require you to rewrite classes that use an injected IDataBaseSqlServerDapper.
My situation was similar to this, but a little bit simpler. I am posting my solution for anyone landing here with a problem like mine.
The Problem
I needed a way to use multiple instances of a single concrete-type (in my case NPoco.Database) initialized with different parameters (connection string names). Since the SimpleInjector doc examples use classes that implement ILogger and all have parameter-less constructors, I was finding it difficult to figure out how to make my scenario work.
The Solutuion
I finally came up with creating a simple sub-class of NPoco.Database for each database I needed to connect to, then using Container.RegisterConditional to register the instances. Since RegisterConditional does not have an overload that takes a constructor function, I had to give each of these sub-classes parameter-less constructors which called the base Database class with the proper connection string name. Lastly, some of the consumers were from an external NuGet package (internal to my organization) and relied on IDatabase being injected, not a derived type, so I could not just rely on registering derived types and letting SimpleInjector figure out based on that alone.
The Code
With all that said, here is my solution.
Sub-Classes of NPoco.Database
public class FirstSubDatabase : Database
{
public FirstSubDatabase()
: base("FirstSubConnection") { }
}
public class SecondSubDatabase : Database
{
public SecondSubDatabase()
: base("SecondSubConnection") { }
}
Registration
container.RegisterConditional<IDatabase, FirstSubDatabase>(
Lifestyle.Scoped,
c => c.Consumer.ImplementationType.FullName?.StartsWith(
"external.lib.", StringComparison.OrdinalIgnoreCase) ?? false);
container.RegisterConditional<IDatabase, SecondSubDatabase>(
Lifestyle.Scoped,
c => c.Consumer.ImplementationType == typeof(LocalConsumerClass));
Note: "external.lib." is just the namespace of everything from the external NuGet package. This saves future editors (including myself) of having to spend time figuring out why taking a dependency on another service from that package be instantiated.
In ASP.NET Core 2 Web Api, I want to use dependency injection to inject httpClientA instance of HttpClient to ControllerA, and an instance httpClientB of the HttpClient to ControllerB.
The DI registration code would look something like:
HttpClient httpClientA = new HttpClient();
httpClientA.BaseAddress = endPointA;
services.AddSingleton<HttpClient>(httpClientA);
HttpClient httpClientB = new HttpClient();
httpClientB.BaseAddress = endPointB;
services.AddSingleton<HttpClient>(httpClientB);
I know I could subclass HttpClient to make a unique type for each controller, but that doesn't scale very well.
What is a better way?
UPDATE
Specifically regarding HttpClient Microsoft seems to have something in the works
https://github.com/aspnet/HttpClientFactory/blob/dev/samples/HttpClientFactorySample/Program.cs#L32 - thanks to #mountain-traveller (Dylan) for pointing this out.
Note: This answer uses HttpClient and a HttpClientFactory as an example but easily applies to any other kind of thing. For HttpClient in particular, using the new IHttpClientFactory from Microsoft.Extensions.Http is preferred.
The built-in dependency injection container does not support named dependency registrations, and there are no plans to add this at the moment.
One reason for this is that with dependency injection, there is no type-safe way to specify which kind of named instance you would want. You could surely use something like parameter attributes for constructors (or attributes on properties for property injection) but that would be a different kind of complexity that likely wouldn’t be worth it; and it certainly wouldn’t be backed by the type system, which is an important part of how dependency injection works.
In general, named dependencies are a sign that you are not designing your dependencies properly. If you have two different dependencies of the same type, then this should mean that they may be interchangeably used. If that’s not the case and one of them is valid where the other is not, then that’s a sign that you may be violating the Liskov substitution principle.
Furthermore, if you look at those dependency injection containers that do support named dependencies, you will notice that the only way to retrieve those dependencies is not using dependency injection but the service locator pattern instead which is the exact opposite of inversion of control that DI facilitates.
Simple Injector, one of the larger dependency injection containers, explains their absence of named dependencies like this:
Resolving instances by a key is a feature that is deliberately left out of Simple Injector, because it invariably leads to a design where the application tends to have numerous dependencies on the DI container itself. To resolve a keyed instance you will likely need to call directly into the Container instance and this leads to the Service Locator anti-pattern.
This doesn’t mean that resolving instances by a key is never useful. Resolving instances by a key is normally a job for a specific factory rather than the Container. This approach makes the design much cleaner, saves you from having to take numerous dependencies on the DI library and enables many scenarios that the DI container authors simply didn’t consider.
With all that being said, sometimes you really want something like this and having a numerous number of subtypes and separate registrations is simply not feasible. In that case, there are proper ways to approach this though.
There is one particular situation I can think of where ASP.NET Core has something similar to this in its framework code: Named configuration options for the authentication framework. Let me attempt to explain the concept quickly (bear with me):
The authentication stack in ASP.NET Core supports registering multiple authentication providers of the same type, for example you might end up having multiple OpenID Connect providers that your application may use. But although they all share the same technical implementation of the protocol, there needs to be a way for them to work independently and to configure the instances individually.
This is solved by giving each “authentication scheme” a unique name. When you add a scheme, you basically register a new name and tell the registration which handler type it should use. In addition, you configure each scheme using IConfigureNamedOptions<T> which, when you implement it, basically gets passed an unconfigured options object that then gets configured—if the name matches. So for each authentication type T, there will eventually be multiple registrations for IConfigureNamedOptions<T> that may configure an individual options object for a scheme.
At some point, an authentication handler for a specific scheme runs and needs the actual configured options object. For this, it depends on IOptionsFactory<T> whose default implementation gives you the ability to create a concrete options object that then gets configured by all those IConfigureNamedOptions<T> handlers.
And that exact logic of the options factory is what you can utilize to achieve a kind of “named dependency”. Translated into your particular example, that could for example look like this:
// container type to hold the client and give it a name
public class NamedHttpClient
{
public string Name { get; private set; }
public HttpClient Client { get; private set; }
public NamedHttpClient (string name, HttpClient client)
{
Name = name;
Client = client;
}
}
// factory to retrieve the named clients
public class HttpClientFactory
{
private readonly IDictionary<string, HttpClient> _clients;
public HttpClientFactory(IEnumerable<NamedHttpClient> clients)
{
_clients = clients.ToDictionary(n => n.Name, n => n.Client);
}
public HttpClient GetClient(string name)
{
if (_clients.TryGet(name, out var client))
return client;
// handle error
throw new ArgumentException(nameof(name));
}
}
// register those named clients
services.AddSingleton<NamedHttpClient>(new NamedHttpClient("A", httpClientA));
services.AddSingleton<NamedHttpClient>(new NamedHttpClient("B", httpClientB));
You would then inject the HttpClientFactory somewhere and use its GetClient method to retrieve a named client.
Obviously, if you think about this implementation and about what I wrote earlier, then this will look very similar to a service locator pattern. And in a way, it really is one in this case, albeit built on top of the existing dependency injection container. Does this make it better? Probably not, but it’s a way to implement your requirement with the existing container, so that’s what counts. For full defense btw., in the authentication options case above, the options factory is a real factory, so it constructs actual objects and doesn’t use existing pre-registered instances, so it’s technically not a service location pattern there.
Obviously, the other alternative is to completely ignore what I wrote above and use a different dependency injection container with ASP.NET Core. For example, Autofac supports named dependencies and it can easily replace the default container for ASP.NET Core.
Another option is to
use an additional generic type parameter on the interface or a new interface implementing the non generic interface,
implement an adapter/interceptor class to add the marker type and then
use the generic type as “name”
I’ve written an article with more details: Dependency Injection in .NET: A way to work around missing named registrations
Use named registrations
This is exactly what named registrations are for.
Register like this:
container.RegisterInstance<HttpClient>(new HttpClient(), "ClientA");
container.RegisterInstance<HttpClient>(new HttpClient(), "ClientB");
And retrieve this way:
var clientA = container.Resolve<HttpClient>("ClientA");
var clientB = container.Resolve<HttpClient>("ClientB");
If you want ClientA or ClientB automatically injected into another registered type, see this question. Example:
container.RegisterType<ControllerA, ControllerA>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<HttpClient>("ClientA") // Resolve parameter of type HttpClient using name "ClientA"
)
);
container.RegisterType<ControllerB, ControllerB>(
new InjectionConstructor( // Explicitly specify a constructor
new ResolvedParameter<HttpClient>("ClientB") // Resolve parameter of type HttpClient using name "ClientB"
)
);
Use a factory
If your IoC container lacks any ability to handle named registrations, you could inject a factory and let the controller decide how to get the instance. Here is a really simple example:
class HttpClientFactory : IHttpClientFactory
{
private readonly Dictionary<string, HttpClient> _clients;
public void Register(string name, HttpClient client)
{
_clients[name] = client;
}
public HttpClient Resolve(string name)
{
return _clients[name];
}
}
And in your controllers:
class ControllerA
{
private readonly HttpClient _httpClient;
public ControllerA(IHttpClientFactory factory)
{
_httpClient = factory.Resolve("ClientA");
}
}
And in your composition root:
var factory = new HttpClientFactory();
factory.Register("ClientA", new HttpClient());
factory.Register("ClientB", new HttpClient());
container.AddSingleton<IHttpClientFactory>(factory);
Really the consumer of the service should not care where about the implementation of the instance it is using. In your case I see no reason to manually register many different instances of HttpClient. You could register the type once and any consuming instance that needs an instance will get it's own instance of HttpClient. You can do that with AddTransient.
The AddTransient method is used to map abstract types to concrete services that are instantiated separately for every object that requires it
services.AddTransient<HttpClient, HttpClient>();
I have some services in my asp.net mvc application that listen for AMQP messages and invoke methods.
No controllers depend on this, so it won't get instantiated on its own.
I could instantiate it manually, explicitly providing its dependencies with kernel.Get but it feels like I shouldn't have to do that.
Can I make Ninject instantiate classes in singleton scope eagerly even when nothing else depends on it?
You cannot have ninject instantiate stuff in case you don't ask it to instantiate something yourself.
The simple way is to ask ninject to instantiate things at composition root:
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<Foo>();
kernel.Load(AppDomain.CurrentDomain.GetAssemblies()); // loads all modules in assemlby
//...
// resolution root completely configured
kernel.Resolve<IFooSingleton>();
kernel.Resolve<IBarSIngleton>();
There is one alternative, actually, which is not the same, but can be used to achieve a similar effect. It requires that there is at least one single other service instantiated soon enough: Ninject.Extensions.DependencyCreation.
It works like this:
kernel.Bind<string>().ToConstant("hello");
kernel.Bind<ISingletonDependency>().To<SingletonDependency>()
.InSingletonScope();
kernel.DefineDependency<string, ISingletonDependency>();
kernel.Get<string>();
// when asking for a string for the first time
// ISingletonDependency will be instantiated.
// of course you can use any other type instead of string
Why
Ninject is unlike some other containers (for example Autofac) not "built" in stages. There's no concept of first creating the bindings, and then creating the kernel to use them. The following is perfectly legal:
kernel.Bind<IFoo>()...
kernel.Get<IFoo>()...
kernel.Bind<IBar>()...
kernel.Get<IBar>()...
so ninject can't possibly know when you want the singletons to be instantiated. With autofac it's clear and easy:
var containerBuilder = new ContainerBuilder();
containerBuilder
.RegisterType<Foo>()
.AutoActivate();
var container = containerBuilder.Build(); // now
Coming from Guice in Java, I've sorely missed the pattern of eager singletons. They are useful in scenarios where for example modules act as plugins. If you imagine that a service is assembled from modules that are specified in a configuration, you could see a problem of then also trying to specify what this module needs to be auto-instantiated when the application is started.
For me the module is where the composition of the application is defined and separating eager singletons into another place in the code feels more clunky and less intuitive.
Anyway, I've been able to very easily implement this as a layer on top of Ninject, here's the code:
public static class EagerSingleton
{
public static IBindingNamedWithOrOnSyntax<T> AsEagerSingleton<T>(this IBindingInSyntax<T> binding)
{
var r = binding.InSingletonScope();
binding.Kernel.Bind<IEagerSingleton>().To<EagerSingleton<T>>().InSingletonScope();
return r;
}
}
public interface IEagerSingleton { }
public class EagerSingleton<TComponent> : IEagerSingleton
{
public EagerSingleton(TComponent component)
{
// do nothing. DI created the component for this constructor.
}
}
public class EagerSingletonSvc
{
public EagerSingletonSvc(IEagerSingleton[] singletons)
{
// do nothing. DI created all the singletons for this constructor.
}
}
After you've created your kernel, add a single line:
kernel.Get<EagerSingletonSvc>(); // activate all eager singletons
You use it in a module like this:
Bind<UnhandledExceptionHandlerSvc>().ToSelf().AsEagerSingleton();
I am using Microsoft's Unity for dependency injection and I want to do something like this:
IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context
IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);
RepositoryA and RepositoryB both have a constructor that takes an IDataContext parameter, and I want Unity to initialize the repository with the context that I pass it. Also note that IDataContext is not registered with Unity (I don't want 3 instances of IDataContext).
As of today they have added this functionality:
It’s in the latest drop here:
http://unity.codeplex.com/SourceControl/changeset/view/33899
Discussion on it here:
http://unity.codeplex.com/Thread/View.aspx?ThreadId=66434
Example:
container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"
< 2 cents>
What if you later on decide to use a different service that requires more or less than just the context?
The problem with constructor parameters and IoC is that the parameters are ultimately tied to the concrete type being used, as opposed to being part of the contract that the service interface defines.
My suggestion would be that you either resolve the context as well, and I believe Unity should have a way for you to avoid constructing 3 instances of it, or you should consider a factory service that has a way for you to construct the object.
For instance, what if you later on decide to construct a repository that doesn't rely on a traditional database at all, but instead use an XML file to produce dummy-data for the test? How would you go about feeding the XML content to that constructor?
IoC is based around decoupling code, by tying in the type and semantics of the arguments to the concrete types, you really haven't done the decoupling correctly, there's still a dependency.
"This code can talk to any type of repository possibly, as long as it implements this interface.... Oh, and uses a data context".
Now, I know that other IoC containers have support for this, and I had it in my first version of my own as well, but in my opinion, it doesn't belong with the resolution step.
< /2 cents>
Thanks guys ... mine is similar to the post by "Exist". See below:
IUnityContainer container = new UnityContainer();
container.LoadConfiguration();
_activeDirectoryService = container.Resolve<IActiveDirectoryService>(new ResolverOverride[]
{
new ParameterOverride("activeDirectoryServer", "xyz.adserver.com")
});
You can use InjectionConstructor / InjectionProperty / InjectionMethod depending on your Injection Architecture within the ResolvedParameter< T >("name") to get a instance of a pre-registered Object in the container.
In your case this Object must be registered with a Name, and for the same insance you need ContainerControlledLifeTimeManager() as the LifeTimeManager.
_unityContainer.RegisterType<IDataContext,DataContextA>("DataContextA", new ContainerControlledLifeTimeManager());
_unityContainer.RegisterType<IDataContext,DataContextB>("DataContextB");
var repositoryA = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));
var repositoryB = _unityContainer.Resolve<IRepositoryB>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextB")));
The very short answer is: no. Unity currently has no way to pass parameters into the constructor that aren't constant or injected, that I have been able to find. IMHO that's the single biggest thing it's missing, but I think it is by design rather than by omission.
As Jeff Fritz notes, you could in theory create a custom lifetime manager that knows which context instance to inject into various types, but that's a level of hard-coding which seems to obviate the purpose of using Unity or DI in the first place.
You could take a small step back from full DI and make your repository implementations responsible for establishing their own data contexts. The context instance can still be resolved from the container but the logic for deciding which one to use would have to go into the implementation of the repository. It's not as pure, certainly, but it would get rid of the problem.
Another alternative you could use (don't really know if it is a good practice or not) is creating two containers and registering an instance for each:
IDataContext context = _unityContainer.Resolve<IDataContext>();
_unityContainer.RegisterInstance(context);
var repositoryA = _unityContainer.Resolve<IRepositoryA>(); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(); //Same instance of context
//declare _unityContainer2
IDataContext context2 = _unityContainer2.Resolve<IDataContext>(); //New instance
_unityContainer2.RegisterInstance(context2);
var repositoryA2 = _unityContainer2.Resolve<IRepositoryA>(context2); //will retrieve the other instance
hope this helps too
NotDan, I think you may have answered your own question in comments to lassevk.
First, I would use a LifetimeManager to manage the lifecycle and number of instances of IDataContext that Unity creates.
http://msdn.microsoft.com/en-us/library/cc440953.aspx
It sounds like the ContainerControlledLifetimeManager object will give you the instance management that you need. With that LifetimeManager in place, Unity should add the same instance of the IDataContext to all objects that require an IDataContext dependency.