Structure map - understanding Use and Add semantics - c#

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!

Related

How to resolve IoC dynamically by using it's name as string

I have a multiple Implementations for the same interface like the below example
container.Register(Component.For<OrganizationServiceCore.IOrganizationService>().ImplementedBy<SchoolServiceCore.SchoolsProvider.SchoolService>());
OR
container.Register(Component.For<OrganizationServiceCore.IOrganizationService>().ImplementedBy<CompanyServiceCore.CompanyProvider.CompanyService>());
The resolving must depend on a vale in the database,I will get the value from database as a string "SchoolServiceCore.SchoolsProvider.SchoolService" OR
"CompanyServiceCore.CompanyProvider.CompanyService"
How I can use it like the example below:
string serviceName= "CompanyServiceCore.CompanyProvider.CompanyService";
container.Register(Component.For<OrganizationServiceCore.IOrganizationService>().ImplementedBy<serviceName>());
You can try using
string serviceName= "CompanyServiceCore.CompanyProvider.CompanyService";
Type myType= Type.GetType(serviceName);
container.Register(Component.For<OrganizationServiceCore.IOrganizationService>().ImplementedBy<myType>());
and using this to register your type in the IoC container.
I would assume that you are using Windsor Castle as your DI container based on the provided sample code.
I can see at least two different options:
1) Register All and use only the appropriate one
container.Register(
Component.For<OrganizationServiceCore.IOrganizationService>()
.ImplementedBy<SchoolServiceCore.SchoolsProvider.SchoolService>(),
Component.For<OrganizationServiceCore.IOrganizationService>()
.ImplementedBy<CompanyServiceCore.CompanyProvider.CompanyService>());
In this case the first one would win. But if you call the Named builder function as well during the service registrations then you can resolve the appropriate one by its name.
container.Register(
Component.For<OrganizationServiceCore.IOrganizationService>()
.Named("SchoolService")
.ImplementedBy<SchoolServiceCore.SchoolsProvider.SchoolService>(),
Component.For<OrganizationServiceCore.IOrganizationService>()
.Named("CompanyService")
.ImplementedBy<CompanyServiceCore.CompanyProvider.CompanyService>());
...
IOrganizationService svc = container.Resolve<IOrganizationService>("SchoolService");
2) Register only the ONE that is needed
In this case you should use UsingFactoryMethod builder function to delegate the creation process of the appropriate service implementation.
container.Register(
Component.For<OrganizationServiceCore.IOrganizationService>()
.UsingFactoryMethod(
() => OrganizationServiceFactory.CreateService(serviceNameSetting)));
Comparison
The first approach allows to use multiple implementation at the same
time
The first approach chooses the appropriate implementation on
the usage side (this is the so called Service Locator pattern, which
should be avoided if possible if you use DI already)
The second approach registers only a single implementation
The second approach separates registration logic from type deduction logic
For further information please visit the Windsor documentation
var assemblyName = "CompanyServiceCore.CompanyProvider";
var serviceName = "CompanyService";
System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(assemblyName);
var service = assembly.GetTypes().Where(p =>
p.FullName == assemblyName+"."+serviceName
).FirstOrDefault();
container.Register(Component.For<OrganizationServiceCore.IOrganizationService>().ImplementedBy(service));
you can change the assemblyName and serviceName variables depending on the needed value.
don't forgot to add the project reference on the place that you want to use it.

When to use TryAddSingleton or AddSingleton?

I've noticed in some .NET Core examples there are calls to TryAddSingleton, and in some AddSingleton when registering services.
Decompiler shows that TryAdd (called by TryAddSingleton) adds the specified param "descriptor" to the "collection" if the service type hasn't been already registered.
Does it mean that it's always safer to use TryAddSingleton, in case if some other method/library already registered the same class?
As you already noticed, the difference between TryAddSingleton and AddSingleton is that AddSingleton always appends the registration to the collection, while TryAddSingleton only does this when there exists no registration for the given service type.
When multiple registrations exist for the same service type, but a single instance is requested, .NET Core will always return the last one registered. This means that the behavior of AddSingleton is to effectively replace instances for non-collection resolution, for instance:
services.AddSingleton<IX, A>();
services.AddSingleton<IX, B>(); // ‘replaces’ A
IX x = container.GetService<IX>(); // resolves B
For collection resolution however, AddSingleton behaves as a collection ‘append’ of already existing registrations for that service type. For instance:
services.AddSingleton<IX, A>();
services.AddSingleton<IX, B>();
IEnumerable<IX> xs = container.GetServices<IX>(); // resolves A *and* B
With TryAddSingleton however, the registration will not be added when there already exist registrations for the given service type. This means that, independently of when a service type is resolved as one instance or as a collection of instances, the registration will not be added when there is at least one registration. For instance:
services.TryAddSingleton<IX, A>(); // adds A
services.TryAddSingleton<IX, B>(); // does not add B, because of A
IX x = container.GetService<IX>(); // resolves A
services.TryAddSingleton <IX, A>(); // adds A
services.TryAddSingleton <IX, B>(); // does not add B, because of A
IEnumerable<IX> xs = container.GetServices<IX>(); // resolves A only
TryAddSingleton is especially useful for framework and third-party library code that wishes to register its own components to the container. It allows an application developer to override the framework or library’s default registration, even if the application developer registered that component before the framework or third-party AddXXX extension method is called. For instance:
services.TryAddSingleton<IX, A>(); // adds A
services.AddThirdPartyLibrary(); // calls services.TryAddSingleton<IX, B>();
IX x = container.GetService<IX>(); // resolves A
If the third-party library had called AddSingleton instead of TryAddSingleton, the application developer’s A will always be overridden, which is likely to result in unexpected behavior. As an application developer, you typically know what you registered, which makes the use of TryAddSingleton less useful in such a case.
I would even argue that, from perspective of an application developer, the behavior of AddSingleton can be very tricky, because it implicitly overrides an existing registration, without any warning whatsoever. My experience is that this behavior can cause hard to spot configuration errors. A safer design would have been to have AddSingleton, AppendSingleton and ReplaceSingleton methods, where AddSingleton would throw an exception in case a registration exists, and ReplaceSingleton would actually discard the existing registration.

Adding interception on existing registration

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!)

Ninject passing in constructor values

With Ninject, how do you configure the kernel so I can define what constructor values are passing into the instantiation of an object?
I have the following configured in a module:
Bind<IService1>()
.To<Service1Impl>()
.InSingletonScope()
.Named("LIVE");
Bind<IService2>()
.To<Service2Impl>()
.InSingletonScope()
.Named("LIVE")
.WithConstructorArgument(
"service1",
Kernel.Get<IService1>("LIVE"));
Service2Impl takes a constructor parameter of IService1 but I want this to come from the container. I also want to have named bindings as my code will be targeting different versions at runtime.
This seems to work but is it the right way to achieve what I want to do?
Should I be achieving without the use of named bindings and wiring different configuration modules into the kernel?
EDIT
I have used the ToMethod() method now to specify a delegate to call on request of a specific type. This seems a bit nicer as I'll get compile time warnings if the constructor configuration is wrong rather than having to know the name of the parameter I am passing first.
Thanks
I would recommend the WithConstructorParameter overload that takes a lambda like so:
Bind<IService2>()
.To<Service2Impl>()
.InSingletonScope()
.Named("LIVE")
.WithConstructorArgument(
"service1",
ctx => ctx.Kernel.Get<IService1>("LIVE"));
This will ensure that that the resolution of IServive1 happens at the time of activation of Service2Impl and not at startup when the container is created. Whilst in your case it doesn't really matter as Service1Impl is singleton, there could be side effects on doing it in the way you originally wrote it:
The binding for dependency that is injected by WithConstructorArgument has to already exist. This implies that all bindings have to done in a particular order. This creates can get tricky when there are multiple modules involved.
Scoping issues can arise when custom scope is used. Ninject 2.0 introduced cache and collect scope management, binding to a constant is very likely to throw that into disarray.
I used ToMethod in the end, which allowed me to construct the required instance with constructors in order to maintain compile time errors.
For example:
.ToMethod(Func<IContext, T> method)
Bind<IWeapon>().ToMethod(context => new Sword());
It seems you're looking at this the wrong way. Ninject will inject service 1 automatically into service 2 if it has it as constructor argument. There is not need for WithConstructorArgument in this case.
If there are multiple IService1 you should go for conditions. E.g. WhenParentNamed(...)
Maybe the Providers can help you. Bind IService2 To a Provider. and in the Create method of Provider, use Kernel.Get("LIVE") to create the Service2Impl instance.
see the following link to know how to use Provider
https://github.com/ninject/ninject/wiki/Providers%2C-Factory-Methods-and-the-Activation-Context
I think ToConstant() is cleaner, the InSingletonScope is implicit:
Bind<IService2>().ToConstant(new Service2Impl(argument)))
.Named("LIVE");

Can I pass constructor parameters to Unity's Resolve() method?

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.

Categories

Resources