In this scenario I my application is handed an already initialized UnityContainer on which has been registered a type which boils down to this:
container.RegisterType<IService>(new InjectionFactory(c => new Service()));
What I need to achieve is adding an interceptor ServiceInterceptor to the IService registration. I suppose the obvious answer is: Do this by running a second RegisterType<IService> and applying the interceptor as injection members. However, re-creating the provided injection factory and delegate as described below is unfortunately not feasible. The new Service() statement isn't available to me at this point.
container.RegisterType<IService>(
new InjectionFactory(c => new Service()),
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<ServiceInterceptor>());
So: I am looking for a way to add further injection members to an existing ContainerRegistration.
// 1. Get the current container registration
var containerRegistration = container.Registrations
.First(cr => cr.RegisteredType == typeof(IService));
// 2. Is this even possible?
ApplyInterception(
containerRegistration,
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<ServiceInterceptor>());
// 3. Profit!
You could initially register the type as a named registration (using the InjectionFactory) while also providing a default registration (with no name) that just resolves the named registration:
container.RegisterType<IService>("original",
new InjectionFactory(c => new Service()));
container.RegisterType<IService>(
new InjectionFactory(c => c.Resolve<IService>("original")));
So you can resolve IService as you would normally do. However you will now be able to replace the default registration while keeping the original named registration. This way you can work around your issue, where you couldn't re-register IService due to the factory statement not being available at that point.
With this approach in place, at a later point you can override the default IService registration with one where interception is registered and still uses the original named registration for resolving the instance:
container.RegisterType<IService>(
new InjectionFactory(c => c.Resolve<IService>("original")),
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<ServiceInterceptor>());
If you now resolve IService, you will still use the original factory method c => new Service() as it is resolving the "original" named registration, but this time your ServiceInterceptor is also applied.
I have created this fiddle so you can check a full working example.
There is a second approach using Policy Injection. (See Policy Injection section in the msdn).
First configure your type as usual, but leave the door opened for using Policy Injection:
container.RegisterType<IService>(
new InjectionFactory(c => new Service()),
new InterceptionBehavior<PolicyInjectionBehavior>(),
new Interceptor<InterfaceInterceptor>());
At this point your service is registered without any interception being applied. However at a later point you can add a policy injection rule, for example matching your service type name, that adds the interception:
container.Configure<Interception>()
.AddPolicy("yourInterceptor")
.AddMatchingRule<TypeMatchingRule>
(new InjectionConstructor("MyNamespace.Service", true))
.AddCallHandler<ServiceInterceptorHandler>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(),
new InjectionProperty("Order", 1));
Now if you resolve IService, the interception logic in ServiceInterceptorHandler will be applied (This class is basically the same as ServiceInterceptor in the first approach, but implementing ICallHandler instead of IInterceptionBehavior)
Again, check the example in this fiddle
Having a look at both options, I personally feel more comfortable with the first approach, avoiding the overhead of the matching rules.
The first approach would also allow you to easily completely turn off interception by overriding again the IService registration, saving you from the interceptors overhead if you want it completely off. (Both approaches allow you to implement the WillExecute property of the interceptor/handler classes, but you still have the overhead of the interceptors). You can do this using policy injection, but you need another intermediate call handler, see this post
However with the second approach, you could apply this solution to multiple classes using the matching rules (For example all classes in a namespace, or all classes whose name follows a specific pattern, etc. You can take a look at the matching rules here)
In the end you will need to decide which one fits you best. (and there might be other approaches, would love to see them posted!)
Related
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.
I would like to register two different Injection factories for the same type, for example, it could be the two registrations below.
container.RegisterType<BaseSearchProvider>(
new HierarchicalLifetimeManager(),
new InjectionFactory(c =>ExamineManager.Instance.SearchProviderCollection["Setting 1"]));
container.RegisterType<BaseSearchProvider>(
new HierarchicalLifetimeManager(),
new InjectionFactory(c => ExamineManager.Instance.SearchProviderCollection["Setting 2"]));
For now, foreach type I register manually my constructions. I have different services, but some services need to use the first registration and others the second registration? Is there any way to perform this, by using some "Profile" like this?
container.RegisterType<IMeetingSearchService>("using Setting 1")
The only thing I can think off for now as the solution is to inherit the BaseSearchProvider and to register this type so that I can register two different types and adapt all my constructors with this, so I even don't need that selector. But maybe there is another way?
There is a way to resolve by name.
So you need two different derived types of BaseSearchProvider. Lets call them:
SettingsOneSearchProvider & SettingsTwoSearchProvider
Now we can get get the right settings by using the 'ExamineManager.Instance.SearchProviderCollection["settingsname"]' code in the constructor of the two new providers.
In you registration class you add names to the registrations like this:
container.RegisterType<BaseSearchProvider, SettingsOneSearchProvider>("SettingsOne"
new HierarchicalLifetimeManager(),
new InjectionFactory(c =>ExamineManager.Instance.SearchProviderCollection["Setting 1"]));
container.RegisterType<BaseSearchProvider, SettingsTwoSearchProvider>("SettingsOne"
new HierarchicalLifetimeManager(),
new InjectionFactory(c => ExamineManager.Instance.SearchProviderCollection["Setting 2"]));
Now we need an extra resolve method in the registration class to resolve by name:
public static T Resolve<T>(string name)
{
return container.Resolve<T>(name);
}
Now you can resolve one of the two by using this code:
var provider = RegistationClassName.Resolve<BaseSearchProvider>("SettingsOne");
I'm currently trying to wrap a class in decorator and inject in one of the dependencies at runtime. I currently have an interface of IStorage that is implemented by a StorageCacheDecorator and a Storage. The StorageCacheDecorator takes in a IStorage and the Storage object takes in aContext` object. However the context object needs to be passed in every time these classes are resolved.
public interface IStorage
{
}
public class Storage : IStorage
{
public Context Context { get; }
public Storage(Context context)
{
this.Context = context;
}
}
public class StorageCacheDecorator : IStorage
{
public IStorage InnerStorage { get; }
public StorageCacheDecorator(IStorage innerStorage)
{
this.InnerStorage = innerStorage;
}
}
public class Context
{
}
I've omitted the implementation details and the test below gives an example of my problem
[Test]
public void ShouldResolveWithCorrectContext()
{
var context = new Context();
var container = new UnityContainer();
container.RegisterType<Storage>();
container.RegisterType<IStorage>(
new InjectionFactory(c => new StorageCacheDecorator(
c.Resolve<Storage>())));
var resolve = container.Resolve<IStorage>(new DependencyOverride<Context>(context));
Assert.That(resolve, Is.TypeOf<StorageCacheDecorator>());
var cacheDecorator = ((StorageCacheDecorator)resolve);
Assert.That(cacheDecorator.InnerStorage, Is.TypeOf<Storage>());
var storage = ((Storage)cacheDecorator.InnerStorage);
Assert.That(storage.Context, Is.SameAs(context));
}
However if we remove the decorator the test passes
[Test]
public void ShouldResolveWithCorrectContext1()
{
var context = new Context();
var container = new UnityContainer();
container.RegisterType<IStorage, Storage>();
var resolve = container.Resolve<IStorage>(new DependencyOverride<Context>(context));
Assert.That(resolve, Is.TypeOf<Storage>());
Assert.That(((Storage)resolve).Context, Is.SameAs(context));
}
How do I get the InjectionFactory to respect the DependencyOverride?
First of all, I'm pretty sure that what you (and today - me) have stumbled upon is a bug in Unity.
I managed to diagnose it a bit thanks to this excellent article from where I got an example of a BuilderStrategy. After I replaced my InjectionFactory with this extension, it worked for some cases, and didn't work for other.
After some investigation, it seems that all resolutions in Unity work against the same Container and its configuration, and any DependencyOverrides are dragged along the call in an IBuilderContext object, in a set of resolverOverrides which contains policies constructed from DependencyOverrides. The IBuilderContext provides a GetResolverOverride(Type) method which allows the implementation to get the value overrides for given Type.
So, if you explicitly ask the IBuilderContext.GetResolverOverride for an override for your Storage Context, you will get the Same-Context-Object you expect.
However, if you ever try to ask the Container itself, you will get a Context object resolved along the standard rules. Not that overridden-at-the-point-of-resolution.
This is why any attempt to container.Resolve(..) in the InjectionFactory delegate like here:
container.RegisterType<IStorage>(
new InjectionFactory(c => new StorageCacheDecorator(
c.Resolve<Storage>()))); // <-- this C is Container
will fail to satisfy overrides, because.. Container has no idea about overrides!
It would have to be:
container.RegisterType<IStorage>(
new InjectionFactory(c => new StorageCacheDecorator(
builderContext.Resolve<Storage>())));
which, if ever implemented, could access the GetResolverOverride and build a proper Storage with correct override. However, no such method exists, and, what's worse, at this point of code you don't have access to the IBuilderContext - InjectionFactory does not give it to you. Probably only extensions&friends can access that.
Fun fact: IBuilderContext has GetResolverOverride but doesn't have any sorts of .Resolve. So, if you'd take the code from that article and if you used the PreBuildUp as in that article to do your own resolution logic, you'd have to either use Container (and fail on resolver overrides), or get in a hell of inspecting everything and doing manually all sub-resolutions needed to construct the instance. IBuilderContext provides you a pretty-looking NewBuildUp() method, which seems a great shortcut, but .. it uses the base Container and doesn't forward resolver overrides.
Seeing how complicated and unintuitive it is, and how easy it is to accidentally drop that set of resolveroverrides and fallback to vanilla context, I'm pretty sure that InjectionFactory is EVIL/BUGGED/MISDESIGNED/etc: it gives you "c", your main Container instance, so you just have no way of resolving the parameters properly with respect to the overrides. Instead of that main container, we should get some sort of derived container, or extra builder object, etc..
Using the code at found in the article I was able to hack something that used this GetResolverOverride to initialize the new object instance in a way I wanted, but it was in no way generic and totally not reusable (I just called proper .GetResolverOverride to get the value and passed it right into new MyObject(value).. but, god, that's just awful. However, I needed as a part of a test setup, so I can live with that until the code gets refactored.
Now, let's get back to your case. Obviously you could do a similar thing, but it turns out that in case of decorators there is a much easier way: just get rid of the InjectionFactory. Your original instance initialization code was probably more complicated, but if by any chance it actually was as simple as in your example:
container.RegisterType<IStorage>(
new InjectionFactory(c =>
new StorageCacheDecorator( // <- NEW &
c.Resolve<Storage>() // <- RESOLVE
)));
you should have actually used declarative way instead of imperative buggy InjectionFactory:
container.RegisterType<IStorage, StorageCacheDecorator>(
new InjectionConstructor(
new ResolvedParameter<Storage>()
));
the net effect is exactly the same: new object created, the single-argument constructor is called, and Storage is resolved and used as that argument. I tried it with your test cases and it worked just fine.
Instead of 'ResolvedParameter` you can also use direct object instances, like:
container.RegisterType<IStorage, StorageCacheDecorator>(
new InjectionConstructor(
"foo", 5, new Shoe()
));
but, just as with new StorageDecorator in your original example, the InjectionConstructor needs to get all of the parameters for the constructor, and obviously we won't get a compile-time error when the constructor parameters change in the future. It's also much more limited than InjectionFactory as it needs to get all parameters specified up front.
All the more reason for for hating Unity..
I have the following code with NServiceBus & StructureMap 2.6.2 wired up together:
var bus = Configure.WithWeb().StructureMapBuilder(container)
ObjectFactory.Container.Configure(r =>
r.For<IBus>().Singleton().Use(Configure.Instance.CreateBus().Start())
);
container.Configure(r => r.For<IBus>().Singleton().Add<MyBus>().Named("named"));
I want first registration to be a default one, second registration to be available as a named one. But when I run:
var bus1 = container.GetInstance<IBus>();
var bus2 = container.GetInstance<IBus>("named");
I get both instances of type MyBus. According to this question first instance must come from first registration (of type UnicastBus) but it is not.
Am I understanding Use and Add semantics wrong?
You are registering the first instance in the ObjectFactory container instance. The second instance is being registered in a local container instance named container.
For this behavior to work right, you need to use the same container instance for both registrations.
On a side note, you should never use the ObjectFactory static instance (as per the documentation).
The static ObjectFactory wrapper for Container is still available in 3.0, but we strongly recommend against using it for new applications. It only exists for easier compatibility with older installations.
Both registrations:
ObjectFactory.Container.Configure(r =>
r.For<IBus>().Singleton().Use(Configure.Instance.CreateBus().Start())
);
and
container.Configure(r => r.For<IBus>().Singleton().Add<MyBus>().Named("named"));
are applied do different instances of container (container != ObjectFactory.Container). This results in container having only one registration of IBus (MyBus) and that is why you can only resolve this dependency. When you register only one type (even if it is named instance) for specific plugin type you are able to resolve it when using container.GetInstance<TPluginType>(). To fix this issue and have expected behavior you need to change this registration:
ObjectFactory.Container.Configure(r =>
r.For<IBus>().Singleton().Use(Configure.Instance.CreateBus().Start())
);
with this:
container.Configure(r =>
r.For<IBus>().Singleton().Use(Configure.Instance.CreateBus().Start())
);
Tested this issue in both versions of SM (2.6 and 3+) and the behavior is the same on these versions.
Hope this helps!
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.