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.
Related
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.
I have a (growing) list of Data-Generators. The generator that I need is created by a factory class. The generators all implement a common Interface, which includes among other things a static string name.
What I would like to do: Call the factory.Create method with a string parameter for the above mentioned name. The create method finds the generator with this name and returns a new instance of said generator.
Bonus in my opinion of this way to do it: I only have to add new generator classes without having to edit the factory.
Question:
Is this a good way to handle this problem?
How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
Is it correct to call this way of working a factory, or is this some different pattern?
In the end I would call the factory like this (simplified):
//Caller
public DataModel GetData2()
{
var generator = new DataFactory().Create("Gen.2");
return generator.GetData();
}
//Factory
public class DataFactory
{
public AbstractDataGenerator Create(string type)
{
//Here the magic happens to find all implementations of IDataGenerator
var allGenerators = GetImplementations();
var generator = allGenerators.FirstOrDefault(f => f.name == type);
if (generator != null)
return (AbstractDataGenerator)Activator.CreateInstance(generator);
else
return null;
}
}
//Interface
public abstract class AbstractDataGenerator
{
public static string name;
public abstract DataModel GetData();
}
//Data-Generators
public class DataGen1 : AbstractDataGenerator
{
public static string name = "Gen.1";
public DataModel GetData()
{
return new DataModel("1");
}
}
public class DataGen2 : AbstractDataGenerator
{
public static string name = "Gen.2";
public DataModel GetData()
{
return new DataModel("2");
}
}
Should the magic GetImplementations() in the factory be done via Reflection or somehow different? Should I use a completely different approach?
Since answers refer to IoC and DI: This project uses NInject already, so it would be available.
Switched from interface to abstract class.
Is this a good way to handle this problem?
Having a factory to get an instance of the logic class you need by some key - I believe it is a good way. It is a pattern that I use a lot myself. About the way you have your key - I'd prefer to not have it as a static member (regardless to the fact that interfaces can't have static members) but just as a property and to add a base class to the IDataGenerator. That base class will have a constructor that will get the name - That way each new DataGenerator you create will have to set it and you wont forget.
About having the name as a string - I personally prefer having it "strongly typed". What I mean is that if I pass Gen . 2 instead of Gen.2 with strings I will discover this problem only in runtime. Possible other ways (if you want, because a simple string is fine too - a matter of taste):
Replace strings with an enum
Have a static class with static readonly strings for all your values - then in your code use those values. You get the benifits of the intellisense and of not getting the string wrong but better than enum - you can just still pass strings that are not in the "list" so you can add new ones as add-ons.
Have a RequestGenerator object, with each Generator being IDataGenerator<TGeneratorRequest>. This might be an overkill but if you have also extra information you need for the creating of a DataGenerator which differs between them then consider it .
How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
Yes, reflection can be a good way to do so. However, I would suggest to read into Dependency Injection and IoC Containers like Castle Windsor for example. There are things out there that already implement it for you, so why to re-invent the wheel :)
DI is a life changer concept in my opinion
Is it correct to call this way of working a factory, or is this some different pattern?
Yap. It is a Factory
Should the magic GetImplementations() in the factory be done via Reflection or somehow different?
See answer for question 2
This is where constructor injection can REALLY shine. Look into dependency injection tools and employ one! It also checks your "Bonus" request.
Here's what your factory might look like with constructor injection:
public class DataFactory
{
private Dictionary<string, IDataGenerator> generators;
public DataFactory(IDataGenerator[] generatorReferences)
{
this.generators = generatorReferences
.ToDictionary(k => k.name, v => v);
}
public IDataGenerator Create(string type)
{
IDataGenerator generator = null;
this.generators.TryGetValue(type, out generator);
return generator;
}
}
Most DI software has the capability to automatically scan assemblies for implementations of a certain type (e.g. IDataGenerator) and register those with itself, when it constructs an instance of your DataFactory it'll automatically include them.
I have this code:
using (container.BeginLifetimeScope())
{
RenderWord instruction = new RenderWord();
var instances = container.GetAllInstances<IInstructionHandler<RenderWord>>();
var firstInstance = result.First();
}
instances is of type IEnumerable<IInstructionHandler<RenderWord>>
firstInstance is of type IInstructionHandler<RenderWord> that in reality is an instance of a decorator that decorates another decorator that decorates another decorator ...
At runtime the actual class instances is of type ContainerControlledCollection<IInstructionHandler<RenderWord>> and this ContainerControlledCollection class holds a very useful piece of information - the underlying ImplementationType.
Is there any way for me to get to the ContainerControlledCollection or the producers[0].Value.ImplementationType at runtime because I’d really like to be able to discover the base implementation type underneath the chain of decorators.
I think #atomaras might have a good point about your abstraction, although I think it would be fine when you only use this information inside your Composition Root, since your Composition Root is already aware of every implementation in the system.
I think there are a few ways to get to this information:
Use the DecoratorPredicateContext information that is supplied to the RegisterDecorator extension method:
var typeMapping = new Dictionary<Type, Type>();
container.RegisterDecorator(typeof(IInstructionHandler<>), typeof(FakeDecorator<>), c =>
{
typeMapping[c.ServiceType] = c.ImplementationType;
// or perhaps even use c.AppliedDecorators property to see which decorators
// are applied.
// return false to prevent the decorator from being applied.
return false;
});
You can make a fake registration that Simple Injector will call for every IInstructionHandler<T> in the system, but you prevent it from being applied by supplying a predicate that will always return false. You can use the info supplied by Simple Injector in the DecoratorPredicateContext to find out what the actual ImplementationType is.
Alternatively, you can inject an DecoratorContext instance (v2.6 and up) into the top most decorator (as explained here). The DecoratorContext contains the same information as the DecoratorPredicateContext does, but this object will automatically be injected by Simple Injector into a decorator that depends on. It allows you to make the decision inside a decorator, which might be very convenient in your case.
Add an an IDecorator abstraction to the system to allow traversing the decorator chain.
By letting each decorator implement a IDecorator interface that allows access to the decoratee (just as done here) you can traverse the decorator chain and find the actual implementation type:
public interface IDecorator
{
object Decoratee { get; }
}
public static class DecoratorHelpers
{
public static IEnumerable<object> GetDecoratorChain(IDecorator decorator)
{
while (decorator != null)
{
yield return decorator;
decorator = decorator.Decoratee as IDecorator;
}
}
}
You can implement your decorators with this interface as follows:
public class SomeDecorator<T> : IInstructionHandler<T>, IDecorator
{
private readonly IInstructionHandler<T> decoratee;
public SomeDecorator(IInstructionHandler<T> decoratee)
{
this.decoratee = decoratee;
}
object IDecorator.Decoratee { get { return this.decoratee; } }
}
When you implemented this interface on all your decorators, you will be able to do this:
var implementationTypes =
from handler in container.GetAllInstances<IInstructionHandler<RenderWord>>()
let mostInnerDecorator =
DecoratorHelpers.GetDecoratorChain(handler as IDecorator).LastOrDefault()
let implementation = mostInnerDecorator != null ? mostInnerDecorator.Decoratee : handler
select implementation.GetType()
Register a list of Registration instances in one of the RegisterAll overloads, since the Registration object knows about the actual implemenation type.
But instead of point 3, you might as well use the list of implemenation types that you used to create those registrations:
typeMapping[serviceType] = implementationTypes;
container.RegisterAll(serviceType, implementationTypes);
Simple Injector will resolve the registered implementations always in the same order as they are registered (this is guaranteed). So when you resolve a collection of things, you will already have the list of implementations that is layed out in the same order.
Why dont you just check the type of the firstInstance? Wouldn't that give you the actual implementation type?
I have to say though that the fact that you need to know the implementation type is a good indication of problems with your abstraction.
I am in the process of refactoring a rather large portion of spaghetti code. In a nutshell it is a big "God-like" class that branches into two different processes depending in some condition. Both processes are lengthy and have lots of duplicated code.
So my first effort has been to extract those two processes into their own classes and putting the common code in a parent they both inherit from.
It looks something like this:
public class ExportProcess
{
public ExportClass(IExportDataProvider dataProvider, IExporterFactory exporterFactory)
{
_dataProvider = dataProvider;
_exporterFactory = exporterFactory;
}
public void DoExport(SomeDataStructure someDataStructure)
{
_dataProvider.Load(someDataStructure.Id);
var exporter = _exporterFactory.Create(_dataProvider, someDataStructure);
exporter.Export();
}
}
I am an avid reader of Mark Seemann's blog and in this entry he explains that this code has a temporal coupling smell since it is necessary to call the Load method on the data provider before it is in a usable state.
Based on that, and since the object is being injected to the ones returned by the factory anyway, I am thinking of changing the factory to do this:
public IExporter Create(IExportDataProvider dataProvider, SomeDataStructure someDataStructure)
{
dataProvider.Load(someDataStructure.Id);
if(dataProvider.IsNewExport)
{
return new NewExportExporter(dataProvider, someDataStructure);
}
return new UpdateExportExporter(dataProvider, someDataStructure);
}
Because of the name "DataProvider" you probably guessed that the Load method is actually doing a database access.
Something tells me an object doing a database access inside the create method of an abstract factory is not a good design.
Are there any guidelines, best practices or something that say this is effectively a bad idea?
Thanks for your help.
Typically, a factory is used to resolve concrete types of a requested interface or abstract type, so you can decouple consumers from implementation. So usually a factory is just going to discover or specify the concrete type, help resolve dependencies, and instantiate the concrete type and return it. However, there's no hard or fast rule as to what it can or can't do, but it is sensible to give it enough access to only to resources that it needs to resolve and instantiate concrete types.
Another good use of a factory is to hide from consumers types dependencies that are not relevant to the consumer. For example, it seems IExportDataProvider is only relevant internally, and can be abstracted away from consumers (such as ExportProcess).
One code smell in your example, however, is how IExportDataProvider is used. The way it currently seems to work, you get an instance of it once, but it's possible to change its state in subsequent usages (by calling Load). This can lead to issues with concurrency and corrupted state. Since I don't know what that type does or how it's actually used by your IExporter, it's hard to make a recommendation. In my example below, I make an adjustment so that we can assume that the provider is stateless, and instead Load returns some sort of state object that the factory can use to resolve the concrete type of exporter, and then provide data to it. You can adjust that as you see fit. On the other hand, if the provider has to be stateful, you'll want to create an IExportDataProviderFactory, use it in your exporter factory, and create a new instance of the provider from the factory for each call to exporter factory's Create.
public interface IExporterFactory
{
IExporter Create(SomeDataStructure someData);
}
public class MyConcreteExporterFactory : IExporterFactory
{
public MyConcreteExporterFactory(IExportDataProvider provider)
{
if (provider == null) throw new ArgumentNullException();
Provider = provider;
}
public IExportDataProvider Provider { get; private set; }
public IExporter Create(SomeDataStructure someData)
{
var providerData = Provider.Load(someData.Id);
// do whatever. for example...
return providerData.IsNewExport ? new NewExportExporter(providerData, someData) : new UpdateExportExporter(providerData, someData);
}
}
And then consume:
public class ExportProcess
{
public ExportProcess(IExporterFactory exporterFactory)
{
if (exporterFactory == null) throw new ArgumentNullException();
_exporterFactory = factory;
}
private IExporterFactory _exporterFactory;
public void DoExport(SomeDataStructure someData)
{
var exporter = _exporterFactory.Create(someData);
// etc.
}
}
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.