Resolving different instances using unity container with multiple dependancies - c#

I wanna resolve different instances with the same interface. I read something about named registrations which should probably push me in the right direction except I can't seem to fit them in a hierarchy structure.
public interface IServiceType
{
}
public interface IServiceDependancy
{
}
public class main
{
var container = new UnityContainer();
container.RegisterType(typeof(IServiceType), typeof(ServiceType));
container.RegisterType(typeof(IServiceDependancy), typeof(ProductionServiceDependancy), "Production");
container.RegisterType(typeof(IServiceDependancy), typeof(TestServiceDependancy), "Test");
}
How can I resolve the IServiceType twice (or more)?
First time with my TestServiceDependancy.
Second time with my ProductionServiceDependancy
Kind regards

It seems to me that you don't need named registrations. Since you are talking about a ProductionServiceDependency and TestServiceDependency you would typically just want to register either one of them, and only use a different one when the application is restarted (because of a different configuration setting). In other words, you can simply do this:
if (ConfigurationManager.AppSettings["IsTest"] != string.Empty) {
container.RegisterType(typeof(IServiceDependency), typeof(TestServiceDependancy));
else
container.RegisterType(typeof(IServiceDependency), typeof(ProductionServiceDependency));
Or perhaps simply:
container.RegisterType(typeof(IServiceDependency),
ConfigurationManager.AppSettings["IsTest"] != string.Empty
? typeof(TestServiceDependency)
: typeof(ProductionServiceDependency));
In case you need to be able to swap the implementation based on some runtime condition (perhaps because you need to be able two change the configuration at runtime), you should hide the two implementations behind a proxy:
public sealed class ServiceDependencySelectionProxy : IServiceDependency {
private Func<bool> selectionPredicate;
private IServiceDependency trueService;
private IServiceDependency falseService;
public ServiceDependencySelectionProxy(Func<bool> selectionPredicate,
IServiceDependency trueService, IServiceDependency falseService) {
this.selectionPredicate = selectionPredicate;
this.trueService = trueService;
this.falseService = falseService;
}
object IServiceDependency.ItsMethod(object param) {
return this.selectionPredicate()
? this.trueService.ItsMethod(param)
: this.falseService.ItsMethod(param);
}
}
Now you can register the ServiceDependencySelectionProxy as IServiceDependency and this will hide the fact that there is a some runtime selection going on, while keeping your object graph itself completely static (as in: its structure wont change at runtime) and this keeps your object graph verifiable.
Here's an example of how to register this ServiceDependencySelectionProxy:
container.RegisterType<IServiceDependancy, ProductionServiceDependancy>("Production");
container.RegisterType<IServiceDependancy, TestServiceDependancy>("Test");
container.Register<IServiceDependency>(new InjectionFactory(c =>
new ServiceDependencySelectionProxy(
() => IsApplicationTestSwitchEnabled(),
container.Resolve<IServiceDependency>("Test"),
container.Resolve<IServiceDependency>("Production"))));

Related

Can you use Autofac's Owned with a marker interface?

I want to use Autofac to create a new instance of one or several WCF channels for a given unit of work. I'd like to use the command pattern to represent units of work, i.e. a given command class is injected with the channel(s) it needs and implements a bunch of related operations.
I tried the following:
interface IUnitOfWork
{
}
class FooCall : IUnitOfWork
{
readonly BarChannel _channel;
public FooCall(BarChannel channel)
{
Console.WriteLine($"FooCall({new {channel}})");
_channel = channel;
}
public string Foo()
{
return "FOO";
}
}
class BarChannel
{
public BarChannel()
{
Console.WriteLine("BarChannel()");
}
}
class FooService
{
Func<Owned<FooCall>> _helperFn;
public FooService(Func<Owned<FooCall>> helperFn)
{
_helperFn = helperFn;
}
public void CallFoo()
{
using (var helper = _helperFn())
{
Console.WriteLine($"CallFoo(), helper={helper}");
helper.Value.Foo();
}
}
}
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<BarChannel>().InstancePerOwned<IUnitOfWork>();
builder.RegisterType<FooCall>().AsImplementedInterfaces().AsSelf();
builder.RegisterType<FooService>();
using (var scope = builder.Build().BeginLifetimeScope())
{
Console.WriteLine("call 1");
scope.Resolve<FooService>().CallFoo();
Console.WriteLine("call 2");
scope.Resolve<FooService>().CallFoo();
}
}
}
In short: a service method creates an owned unit of work; the unit of work is injected with a per-owned channel that it calls. The code sample should show two channel instances being created.
Except that it seems that the lifetime scope created for owned dependencies is only tagged with the type as which the dependency was resolved - i.e. as FooCall, not as IUnitOfWork. If I register BarChannel as InstancePerOwned<FooCall>, the code works; as is, registered as InstancePerOwned<IUnitOfWork>, it fails to resolve FooService since it can't find a matching lifetime scope. Am I missing something or is what I want to do not possible with Autofac? I'd rather not have to register all my WCF channels as instance-per-owned for every command class, that seems like it would get pretty verbose. Another workaround would be using instance-per-depedency and resolving a Func directly, but that won't let me say compose units of work while reusing channels and their dependencies between them.
The problem is that InstancePerOwned<T> is really just a special case of InstancePerMatchingLifetimeScope(params object[] lifetimeScopeTag), where the scope is tagged with something like typeof(T). As it stands, there needs to be a direct link between the tag provided there and the one attached to the scope when attempting to resolve, which is always set to the type of whatever's inside that specific Owned<> dependency. There's no additional logic to imply relations between types at that point, it's just a direct match on the tags.
However, InstancePerMatchingLifetimeScope does allow multiple tags to be specified, so it's possible to do something like:
builder.RegisterType<BarChannel>()
.InstancePerMatchingLifetimeScope(new TypedService(typeof(FooCall)),new TypedService(typeof(AnotherUnitOfWork)));
To wrap this up a bit more neatly you could use:
private static IEnumerable<Type> GetTypesImplementingInterface<TInterface>()
{
return AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(TInterface).IsAssignableFrom(p));
}
and then a new extension method:
public static class AutofacRegistrationBuilderExtensions
{
public static IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> InstancePerOwned<TLimit, TActivatorData, TRegistrationStyle>(
this IRegistrationBuilder<TLimit, TActivatorData, TRegistrationStyle> builder, IEnumerable<Type> serviceTypes)
{
return builder.InstancePerMatchingLifetimeScope(serviceTypes.Select(s => new TypedService(s)).ToArray());
}
}
The usage would then just be:
builder.RegisterType<BarChannel>().InstancePerOwned(GetTypesImplementingInterface<IUnitOfWork>());
I'm not sure if the last part there would be worth pulling into Autofac itself, but I guess if it did then it might be better to combine the two methods above together and retrieve the list of types applicable from existing registrations, e.g. something like
InstancePerOwnedImplementing<TInterface>();
Alternatively, it would probably be a bit messy to extend the matching scope logic to check the relationship between types at resolution time, since not all tags are of the type Type.

Autofac filter resolved IEnumerable implementations

Is it possible to filter dependencies when resolving IEnumerable in autofac?
I have multiple implementations of an interface (IHandler in the example below) which are defined & registered using an Autofac module in isolated projects. I would like to be able to filter the implementations when resolving in the parent type (Processor in the example below).
The IHandler implementations could be injected into the Processor and filtered in the ctor but this would require resolving all implementations regardless whether they are required which is wasteful.
public interface IHandler { }
public class Handler1 : IHandler { }
public class Handler2 : IHandler { }
public class Handler3 : IHandler { }
public class Processor {
public IEnumerable<IHandler> Handlers;
public Processor(IEnumerable<IHandler> handlers) {
Handlers = handlers;
}
}
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Handler1>().As<IHandler>();
builder.RegisterType<Handler2>().As<IHandler>();
builder.RegisterType<Handler3>().As<IHandler>();
builder.RegisterType<Processor>().AsSelf();
var container = builder.Build();
var processor = container.Resolve<Processor>();
}
As only 1 key can be resolved at a time, my attempt with keys didnt work:
[Flags]
public enum HandlerType
{
One = 1,
Two = 2,
Three = 4
}
builder.RegisterType<Handler1>().Keyed<IHandler>(HandlerType.One);
builder.RegisterType<Handler2>().Keyed<IHandler>(HandlerType.Two);
builder.RegisterType<Handler3>().Keyed<IHandler>(HandlerType.Three);
var enabledHandlers = HandlerType.One | HandlerType.Three;
builder.RegisterType<Processor>().AsSelf()
.WithParameter(ResolvedParameter.ForKeyed<IEnumerable<IHandler>>(enabledHandlers));
I would recommend using the Meta<T> and Lazy<T> implicit relationship types to allow the processor to read config and control all that at runtime. That would also allow you to filter differently in different conditions or turn filtering off entirely without having to change any keys.
Register the handlers with metadata instead of as keyed services...
builder.RegisterType<Handler1>()
.As<IHandler>()
.WithMetadata("type", HandlerType.One);
builder.RegisterType<Handler2>()
.As<IHandler>()
.WithMetadata("type", HandlerType.Two);
builder.RegisterType<Handler3>()
.As<IHandler>()
.WithMetadata("type", HandlerType.Three);
Update your processor to take IEnumerable<Meta<Lazy<IHandler>>> and filter during construction or at some later point when the handlers are needed, your call.
public class Processor
{
private readonly IHandler[] _handlers;
public Processor(IEnumerable<Meta<Lazy<IHandler>>> handlers)
{
this._handlers =
handlers
.Where(h => h.Metadata["type"] == HandlerType.One || h.Metadata["type"] == HandlerType.Three)
.Select(h => h.Value.Value)
.ToArray();
}
}
Each item coming in to the constructor will be a Meta<Lazy<IHandler>>:
Meta<T> has a Metadata dictionary to query and the Value will be the Lazy<IHandler>.
Lazy<T> will not resolve/construct the handler until you call the Value property, so it won't be expensive or cause resolutions you don't want.
So item.Value.Value will be the resolved IHandler (as you see in the LINQ above).
The stuff in the Where filter could be based on config or anything else. But the real win here is that if you still need to resolve all the handlers somewhere else...
public OtherHandlerConsumer(IEnumerable<IHandler> handlers)
...that will still work. You can't do that if they're all keyed. Plus you can add as much metadata as you want to the registrations or even define more robust strongly typed metadata so you can make smarter decisions about which handlers you want.
If you can provide proper filter during container set up phase (as you do in your sample code), you could change your Processor type registration to the following:
builder.RegisterType<Processor>().AsSelf()
.WithParameter((p, c) => p.Name == "handlers",
(p, c) => new[]
{
c.ResolveKeyed<IHandler>(HandlerType.One),
c.ResolveKeyed<IHandler>(HandlerType.Three)
});
Values you need to use could be taken from anywhere you want, from config file too.
Since the registered handlers are based on a configuration switch, it means that the selected handlers won't change at runtime. This is very different than selecting the handlers based on some runtime condition. I therefore propose something similar to this:
var handlerIds = ConfigurationManager.AppSettings["Handlers"].Split(',');
if (handlerIds.Contains("1")) builder.RegisterType<Handler1>().As<IHandler>();
if (handlerIds.Contains("2")) builder.RegisterType<Handler2>().As<IHandler>();
if (handlerIds.Contains("3")) builder.RegisterType<Handler3>().As<IHandler>();
if (handlerIds.Contains("4")) builder.RegisterType<Handler4>().As<IHandler>();
// etc
builder.RegisterType<Processor>().AsSelf();

Is this correct use of Dependency Injection?

I have a service layer that retrieves a DTO from a repository. Depending on a property in that DTO I need to use one of two strategies to perform calculations on the DTO. I have created a factory to return the appropriate strategy and I'm using a DI container (Munq) to instantiate the object.
public class CalculationFactory
{
private readonly IDependencyResolver _resolver;
public CalculationFactory(IDependencyResolver resolver)
{
ThrowIfNullArgument(resolver, "resolver", typeof(IDependencyResolver));
_resolver = resolver;
}
public static ICalculation CreateCalculator(int serviceType)
{
switch (serviceType)
{
case 1: return _resolver.Resolve<ICalculation>("Type1");
case 2: return _resolver.Resolve<ICalculation>("Type2");
default: return _resolver.Resolve<ICalculation>("InvalidType");
}
}
}
This requires me to pass in the dependency resolver when I instantiate the factory so that it can be used to resolve/instantiate the appropriate calculation to use. Is this the correct approach? If I want to add a new type of calculation then I would need to update the factory CreateCalculator method and register the new type.
Update (long)
I'm not really getting traction on the suggestions I'm afraid. I've gone back to my copy of Mark's DI in .Net and specifically chapter 6 on refactorings. So I have a class MeterReadings and I need to calculate a charge using one of two calculations based on a runtime value. I add an abstract factory to the mix but in my concrete factory I still need to new up the appropriate calculation. I feel like I'm missing the point here:
public enum ServiceType
{
Actuals = 1, CopyBlock,
}
public interface IChargeCalculator
{
decimal CalculateCharge();
}
public interface IChargeCalculatorFactory
{
IChargeCalculator CreateChargeCalculator(ServiceType serviceType);
}
public class MeterReading
{
private readonly IChargeCalculatorFactory chargeCalculatorFactory;
public MeterReading(IChargeCalculatorFactory chargeCalculatorFactory)
{
if (chargeCalculatorFactory == null)
throw new ArgumentNullException("chargeCalculatorFactory");
this.chargeCalculatorFactory = chargeCalculatorFactory;
}
}
public class ConcreteChargeCalculatorFactory : IChargeCalculatorFactory
{
public IChargeCalculator CreateChargeCalculator(ServiceType serviceType)
{
switch (serviceType)
{
case ServiceType.Actuals : return new ActualsChargeCalculator();
default: return new CopyBlockChargeCalculator();
}
}
}
But in my container I can register the different calculators and if I pass in the container as the concrete factory I get something like the following (not tested) which frankly looks fairly reasonable to me. Any feedback/clarification would be welcome.
Container.Register<IChargeCalculator>("Actuals",
c => new ActualsChargeCalculator());
Container.Register<IChargeCalculator>("CopyBlock",
c => new CopyBlockChargeCalculator());
...
public enum ServiceType
{
Actuals = 1, CopyBlock,
}
public interface IChargeCalculator
{
decimal CalculateCharge();
}
public class MeterReading
{
private readonly IDependencyResolver chargeCalculatorFactory;
private ServiceType serviceType;
public MeterReading(IDependencyResolver chargeCalculatorFactory)
{
if (chargeCalculatorFactory == null)
throw new ArgumentNullException("chargeCalculatorFactory");
this.chargeCalculatorFactory = chargeCalculatorFactory;
}
public decimal Charge
{
get
{
return chargeCalculatorFactory.Resolve<IChargeCalculator>(serviceType.ToString());
}
}
}
Yes, I would say you are doing it in a proper way.
Though you write that you need to "pass in the dependency resolver ", is there a reason that you can't have the factory class injected into the class where it is needed? Then the factorys dependency on the dependency resolver should be resolved by the dependency resolver itself (to itself).
I hope that sentence made sense.
I have tried to come up with a "cleaner" solution, but have not found any yet. A solution similar to what is suggested in the question (which is not exactly the same) Dessus links is certainly possible, but I really see that as just moving the same code to another place. Remo also writes that it could be done in a factory class instead of a factory method.
It's a bit like deciding between writing a lampda or a helper class. It mostly comes down to readabilty, and for me a factory method is just to big, and having it in a module initializer or bootstrapper seams to disorganized.
BTW I can recommend Ninject, it is a really good, clean DI. Plus it's documentation uses Ninja examples ;)
I believe this question has been answered here, where it is suggested you use meta data against your bindings and create bindings for each implementation. You then use a binding to pull the meta data to choose which binding to use: Ninject conditional binding based on property value . Possibly this may or may not be possible with Munq? Not sure.
The person (Remo) who answered that question is one of the architects of ninject, and is very knowledgeable. I believe that his answer should hold alot of weight. (I am a basing this of being a subscriber to the ninject mailing list, and seeing him answer about half of all the questions).

SatisfyImportsOnce vs ComposeParts

Can someone please explain the difference between SatisfyImportsOnce and ComposeParts and why one would work where the other doesn't?
Specifically I have a MVC Web application that I am using MEF in. Below is some code (from that application) that works when I use SatisfyImportsOnce but doesn't when I use ComposeParts. My understanding is that ComposeParts creates composable parts from an array of attributed objects and composes them in the specified composition container and that SatisfyImportsOnce composes the specified part by using the specified composition service. To my simple monkey brain even though the English is different they are semantically the same. Both use the CompositionContainer to spit exported types at import targets.
public class FormPartCustomatorFactory
{
[ImportMany(typeof(ICustomRenderer), AllowRecomposition = true)]
private readonly List<Lazy<ICustomRenderer, ICustomRendererMetaData>> _rendererImports = new List<Lazy<ICustomRenderer, ICustomRendererMetaData>>();
private readonly Dictionary<string, Lazy<ICustomRenderer, ICustomRendererMetaData>> _renderers;
public static readonly FormPartCustomatorFactory Instance = new FormPartCustomatorFactory();
static CompositionContainer _container;
private FormPartCustomatorFactory()
{
using (var catalog = new DirectoryCatalog(HttpRuntime.BinDirectory, "*.dll"))
{
_container = new CompositionContainer(catalog);
_container.SatisfyImportsOnce(this); // <- Works
// _container.ComposeParts(this); // DOESN'T Work
_renderers = _rendererImports.ToDictionary(q => q.Metadata.Name, q => q);
}
}
~FormPartCustomatorFactory()
{
_container.Dispose();
}
public static ICustomRenderer Find(string name)
{
return Instance._renderers[name].Value;
}
}
SatisyImportsOnce will compose a type without registering it for recomposition. So, if you intend to use a type without support for recomposition, you can use SatisfyImportsOnce and it will do the work as usual, but any changes in the container (new parts added, or parts removed), then your instance won't automatically be recomposed to offer up these new parts.
In your instance, you are using:
[ImportMany(typeof(ICustomRenderer), AllowRecomposition = true)]
...but through SatisfyImportsOnce, this import won't be recomposed.
If you are not worried about recomposition, you could change your code use constructor injection, so you could do:
[ImportingConstructor]
public FormPartCustomatorFactory(IEnumerable<Lazy<ICustomRenderer, ICustomRendererMetadata>> renderers)
{
if (renderers == null)
throw new ArgumentNullException("renderers");
_renderers = renderers.ToDictionary(r => r.Metadata.Name, r => r);
}
The reason I would suggest constructor injection, is that the set of Lazy<ICustomRenderer, ICustomRendererMetadata> instances are an explicit dependency your type requires, so it would be better to instantiate your type in a usable state, rather than instantiate and then require an additional step to get it ready for first time use.
This makes your FormPartCustomatorFactory type much more testable. To this end, if you were to change the constructor as such, then your method of making it a singleton wouldn't work. Instead, you could take advantage of the lifetime management functionality of MEF, so possibly redesign your type as:
public interface IFormPartCustomatorFactory
{
ICustomRenderer Find(string name);
}
[Export(typeof(IFormPartCustomerFactory)), PartCreationPolicy(CreationPolicy.Shared)]
public class FormPartCustomatorFactory : IFormPartCustomatorFactory
{
private IEnumerable<Lazy<ICustomRenderer, ICustomRendereMetadata>> _renderers;
[ImportingConstructor]
public FormPartCustomatorFactory(IEnumerable<Lazy<ICustomRenderer, ICustomRendererMetadata>> renderers)
{
if (renderers == null)
throw new ArgumentNullException("renderers");
_renderers = renderers;
}
public ICustomRenderer Find(string name)
{
return _renderers
.Where(r => r.Metadata.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)
.Select(r => r.Value)
.FirstOrDefault();
}
}
Doing it this way means that your type is not dependent on MEF, it can be used without it, its more testable, and the CompositionContainer will manage the lifetime of the part, in this case the CreationPolicy.Shared (which is the default for exported types), uses a singleton lifetime strategy. You can then import an instance of IFormPartCustomator, you import the same singleton instance.
I would also argue that calling it a Factory is possibly wrong, as a factory is designed to create new instances, whereas, your type will only create one instance of each ICustomRenderer. If this is the intended behaviour, maybe it would be better called an FormPartCustomatorService, that implements an IFormPartCusomatorService interface? If you want to spin up new instances each time, you could look at ExportFactory<ICustomRenderer, ICustomRendererMetadata>.
As Matthew mentions, SatisfyImportsOnce doesn't register the part for recomposition. This means the MEF container doesn't hold a reference to the part.
In addition, SatisfyImportsOnce only satisfies the imports of a part, but ignores any exports it has. ComposeParts would add the exports to the container too.

Using an Ioc Container at runtime within a factory to determine class initialization

Is this a good pattern? It has a code smell to me with having a factory class aware of the IUnityContainer...
My basic need was to resolve an ICalculationRuleProcess at runtime depending on an Id of a class. It could be based on something other than the Id, I am aware of that... basically I have a known set of Ids that I need to deal with because I bootstrapped the records into the database manually and there is no way to edit the records. With each Id I have a related class. I also have a varying number of constructor parameters within each class that implements the ICalculationRuleProcess, so using an IoC container is extremely helpful versus some crazy switch statement and variable constructor aguments using Activator.CreateInstance
Here is what I did:
Registered the IUnityContainer instance within the container itself. I wasnt sure if this was even possible, but it worked.
Registered all of the ICalculationRuleProcess classes with a unique identifier within the registration (basically just the Id.ToString() of each possible DistributionRule)
Created a factory to determine the correct ICalculationRuleProcess, and had it use the IoC container to figure out the correct class to load.
Registered the factory class (ICalculationRuleProcessFactory) to the IoC container
Wherever the ICalculationRuleProcess needed to be used, I had the class take an ICalculationRuleProcessFactory in its constructor and have it call the Create method to figure out which ICalculationRuleProcess to use.
The code for the factory is here:
public interface ICalculationRuleProcessFactory
{
ICalculationRuleProcess Create( DistributionRule distributionRule );
}
public class CalculationRuleProcessFactory : ICalculationRuleProcessFactory
{
private readonly IBatchStatusWriter _batchStatusWriter;
private readonly IUnityContainer _iocContainer;
public CalculationRuleProcessFactory(
IUnityContainer iocContainer,
IBatchStatusWriter batchStatusWriter )
{
_batchStatusWriter = batchStatusWriter;
_iocContainer = iocContainer;
}
public ICalculationRuleProcess Create( DistributionRule distributionRule )
{
_batchStatusWriter.WriteBatchStatusMessage(
string.Format( "Applying {0} Rule", distributionRule.Descr ) );
return _iocContainer.Resolve<ICalculationRuleProcess>(
distributionRule.Id.ToString() );
}
}
This seems okay to me, given the constraints you described. The most important thing is that all of your rules implement ICalculationRuleProcess and that all consumers of those rules only know about that interface.
It isn't inherently bad that your factory takes the container dependency, especially as an interface. Consider that if you ever had to change container implementations, you could create an IUnityContainer implementation that doesn't use Unity at all (just forward all the members of the interface to their corresponding methods in the replacement container).
If it really bothers you, you can add yet another layer of indirection by creating an agnostic IoC interface with the requisite Register, Resolve, etc. methods and create an implementation that forwards these to Unity.
There is another way you can achieve this without factory taking dependency on IUnityContainer, which is not inherently bad in and of itself. This is just a different way to think about the problem.
The flow is as follows:
Register all different instances of ICalculationRuleProcess.
Get all registered ICalculationRuleProcess and create a creation lambda for each one.
Register ICalculationRuleProcessFactory with a list of ICalculationRuleProcess creation lambdas.
In ICalculationRuleProcessFactory.Create return the right process.
Now the tricky part of this is to preserve the Ids that the registrations were made under. Once solution is to simply keep the Id on the ICalculationProcess interface, but it might not semantically belong there. This is where this solution slips into ugly (which is more of a case of missing functionality in Unity). But, with an extension method and a small extra type, it looks nice when it's run.
So what we do here is create an extension method that returns all registrations with their names.
public class Registration<T> where T : class {
public string Name { get; set; }
public Func<T> CreateLambda { get; set; }
public override bool Equals(object obj) {
var other = obj as Registration<T>;
if(other == null) {
return false;
}
return this.Name == other.Name && this.CreateLambda == other.CreateLambda;
}
public override int GetHashCode() {
int hash = 17;
hash = hash * 23 + (Name != null ? Name.GetHashCode() : string.Empty.GetHashCode());
hash = hash * 23 + (CreateLambda != null ? CreateLambda.GetHashCode() : 0);
return hash;
}
}
public static class UnityExtensions {
public static IEnumerable<Registration<T>> ResolveWithName<T>(this UnityContainer container) where T : class {
return container.Registrations
.Where(r => r.RegisteredType == typeof(T))
.Select(r => new Registration<T> { Name = r.Name, CreateLambda = ()=>container.Resolve<T>(r.Name) });
}
}
public class CalculationRuleProcessFactory : ICalculationRuleProcessFactory
{
private readonly IBatchStatusWriter _batchStatusWriter;
private readonly IEnumerable<Registration<ICalculationRuleProcess>> _Registrations;
public CalculationRuleProcessFactory(
IEnumerable<Registration<ICalculationRuleProcess>> registrations,
IBatchStatusWriter batchStatusWriter )
{
_batchStatusWriter = batchStatusWriter;
_Registrations= registrations;
}
public ICalculationRuleProcess Create( DistributionRule distributionRule )
{
_batchStatusWriter.WriteBatchStatusMessage(
string.Format( "Applying {0} Rule", distributionRule.Descr ) );
//will crash if registration is not present
return _Registrations
.FirstOrDefault(r=>r.Name == distributionRule.Id.ToString())
.CreateLambda();
}
}
//Registrations
var registrations = container.ResolveWithName<ICalculationRuleProcess>(container);
container.RegisterInstance<IEnumerable<Registration<ICalculationRuleProcess>>>(registrations);
After I wrote this I realised that this is more creative lambda douchebaggery than a architecturally pretty solution. But in any case, feel free to get ideas out of it.
Hey Rob, I'm intending to use essentially the same pattern. I've got multiple types of shopping cart item that need to be associated with their own specific set of validator instances of varying class.
I think there is a smell about this pattern and its not that the factory has a reference to the IoC container, its that typically, an IoC container is configured in the application root which is typically the UI layer. If a crazy custom factory was created just to handle these associations then possibly it should be in the domain.
In short, these associations are possibly not part of the overall program structure that's set up before the application runs and so shouldn't be defined in the application root.

Categories

Resources