Structure Map - Inject Collection of Named Instances - c#

This question is very similar to a question I have previously asked (and had answered): Structure Map - Collection of Dependencies in Constructor
In my registry I have the following:
For<IMyObject>().Add<MyObjectType1>().Named("Type1");
For<IMyObject>().Add<MyObjectType2>().Named("Type2");
For<IMyObject>().Add<MyObjectType3>().Named("Type3");
I would like to inject all instances into a constructor, such that I may retrieve any named instance. Example code (produces StructureMap exception):
public class Example
{
private Dictionary<string, IMyObject> _workers;
public Example(Dictionary<string, IMyObject> workers)
{
_workers = workers;
}
public void DoSomeStuff(string mode)
{
var worker = _workers[mode];
worker.DoStuff();
}
}
My reasoning for this approach is to allow external configuration to specify how something should be dealt with (in above example 'mode' would correspond to a named instance).
The actual exception is as follows:
StructureMap.StructureMapException occurred
ErrorCode=202
HResult=-2146232832
Message=StructureMap Exception Code: 202
No Default Instance defined for PluginFamily
I am aware that I can use the StructureMap container in my method DoSomeStuff in order to retrieve a named instance, however, this is something of an anti-pattern.
So to clarify my question:
Can I inject a dictionary (or other collection) of named instances, such that I can refer to them by name?
Hopefully this is clear, please comment back if further explanation is required.
C#: 4.0
StructureMap: 2.5.4.0
Thanks,
Graeme

Instead of injecting a dictionary, it might be better to inject a Func<string, IMyObject> instead. This prevents StructureMap from having to create all IMyObject instances with all their dependencies, while only one of them really needs to be used:
public class Example
{
private Func<string, IMyObject> _workers;
public Example(Func<string, IMyObject> workers)
{
_workers = workers;
}
public void DoSomeStuff(string mode) => _workers(mode).DoStuff();
}
You can register your Example as follows:
For<Example>()
.Use(() => new Example(mode => container.GetInstance<IMyObject>(instanceKey: mode)));

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.

Factory Pattern, selecting by Property

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.

How to use a lambda to specify a constructor argument?

I am not overly familiar with implementing lambdas and expressions, but I've used to this syntax many times in MVC where the lambda is identifying a property on an object:
Html.Label(model => model.Foo)
In my app I am using Ninject conditional bindings to supply the instance of the Settings class which is injected when I request an instance of Class. My Class looks like this:
public class Class
{
private readonly Settings settings;
public Settings Settings { get { return settings; } }
public Class(Settings settings)
{
this.settings = settings;
}
}
I have some code which looks like this to get an instance of Class. I am aware this is the service locator anti pattern, but we have no choice in this case due to other constraints:
var settings = new Settings();
var instance = Ioc.Instance.Get<Class>("settings", settings);
I would like to refactor it to look like this so that it is strongly typed, using a lambda to specify which argument on the constructor I am supplying:
var settings = new Settings();
var instance = Ioc.Instance.Get<Class>(x => x.settings, settings);
So, is this possible, and what would the code look like?
Conceptually there is a lack of the factory (factory interface), so it should be introduced to avoid using the container directly.
The Ninject Factory (factory interface) extension could be used to create the instance, as follows:
Declare a factory interface:
public interface IFactory
{
Class Create(Settings settings);
}
Add a binding to the composition root:
kernel.Bind<IFactory>().ToFactory();
Use the factory to get an instance:
var settings = new Settings();
var factory = Ioc.Instance.Get<IFactory>();
var instance = factory.Create(settings);
Please see the ninject/ninject.extensions.factory for the alternatives.
The problem with constructor argument names and expressions is, that an expression is only valid / complete when it covers all parameters of the constructor. Now i suppose you want to inject a few of the parameters (have ninject handle them) and for one or two specific parameters you want to pass a value, let's say it looks like:
public interface IFoo { }
public class Foo : IFoo
{
public Foo(IServiceOne one, IServiceTwo two, string parameter) {...}
}
Ninject supports ctor expressions, but only for bindings, and they work like this:
IBindingRoot.Bind<IFoo>().ToConstructor(x =>
new Foo(x.Inject<IServiceOne>(), x.Inject<IServiceTwo>(), "staticArgument");
so instead of only specifying the "staticArgument" which you are interested in, you also have to specify IServiceOne and IServiceTwo. What if the constructor changes? Well the call needs to be adapted as well! Lot of work for just passing a single simple parameter.
Now if you still want to do this i'd suggest having a look at the ToConstructor code and creating a similar extension for a Get call which will translate some call
IResolutionRoot.Get<IFoo>(x =>
new Foo(
x.Ignore<IServiceOne>(),
x.Ignore<IServiceTwo>(),
x.UseValue("mystring"));
to
IResolutionRoot.Get<IFoo>(new ConstructorArgument("parameter", "mystring"));
However, i would suggest going with #Sergey Brunov 's answer and use Ninject.Extensions.Factory. Now I think your going to say that it's no good because you'll still have to specify the parameter name,.. which is not refactor safe and a hassle (no code completion...).
However, there's a solution to the problem: Instead of using a constructor argument which "matches" the name of the argument, you can use a type matching argument.
Ok, there's a catch. If you've got multiple arguments of the same type,.. well it won't work. But i think that's seldomly the case and you can still introduce a container data-class to address it:
public class FooArguments
{
string Argument1 { get; set; }
string Argument2 { get; set; }
}
Now how can you use type matching?
There's two ways:
Use a Func<string, IFoo> factory. Just inject Func<string, IFoo> into where you want to create and IFoo.
Extend the Factory extension. Yes you've heard right ;-) It's actually not that difficult. You "just" need to implement a custom IInstanceProvider (also see http://www.planetgeek.ch/2011/12/31/ninject-extensions-factory-introduction/) so you can something like:
public interface IFooFactory
{
IFoo Create([MatchByType]string someParam, string matchByName);
}
(==> use an attribute to tell the factory extension how to pass the parameter to the Get<IFoo>request).
Look at following article -
http://handcraftsman.wordpress.com/2008/11/11/how-to-get-c-property-names-without-magic-strings/
Specifically
public static class Extensions
{
public static string GetPropertyName<T,TReturn>(this Expression<Func<T,TReturn>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return body.Member.Name;
}
}
Note - This method may not work for all possible ways in which one can use expressions to indicate a property name for a class, and hence may need to be enhanced based on your needs (how generic you need it to be).
But essentially, once you have this helper method, your call becomes
var settings = new Settings();
Ioc.Instance.Get<Class>(GetPropertyName(x => x.settings), settings);

Autofac and generics

I have this class
public class MyViewModel<T> where T : class
{
public MyViewModel(
Func<IEnumerable<T>, MyService<T>> myServiceFactory,
IEnumerable<T> list)
{
}
}
and I need to register the Func in the bootstrapper.
I tried something like
builder.Register<Func<IEnumerable<T>, MyService<T>>>(c =>
{
var ctx = c.Resolve<IComponentContext>();
return collection => ctx.Resolve<MyService<T>>(collection);
});
but I can't get it working. Can anyone help me?
As you already noticed, what you're trying to do does not compile. Without defining the T somewhere, the C# compiler doesn't understand. Without a staticly defined T, you would have to define the types using reflection, but you'll hit limits of Autofac and C# pretty soon. You're code becomes very nasty. Instead, you'll have to extract this code in a helper method:
private static void RegisterMyServiceFactory<T>(IContainerBuilder builder) {
builder.Register<Func<IEnumerable<T>, MyService<T>>>(c =>
{
var ctx = c.Resolve<IComponentContext>();
return collection => ctx.Resolve<MyService<T>>(collection);
});
With this method need to call this method for every T you need in your application:
RegisterMyServiceFactory<Customer>(builder);
RegisterMyServiceFactory<Order>(builder);
RegisterMyServiceFactory<Employee>(builder);
This solution isn't particularly nice, but this is because you're missing an abstraction. Instead of letting your consumers depend upon Func<IEnumerable<T>, MyService<T>>, you should create a specific abstraction for consumers to depend upon:
public interface IServiceFactory<T> {
MyService<T> Resolve(IEnumerable<T> collection);
}
And embed your code in an IServiceFactory<T> implementation:
private sealed class AutofacServiceFactory<T> : IServiceFactory<T> {
private readonly IComponentContext context;
public AutofacServiceFactory(IComponentContext context) {
this.context = context;
}
public MyService<T> Resolve(IEnumerable<T> collection) {
return context.Resolve<MyService<T>>(collection);
}
}
You can register this open generic type as follows:
builder.RegisterGeneric(typeof(AutofacServiceFactory<>))
.As(typeof(IServiceFactory<>));
If the builder.Register code is executed by an instance of a MyViewModel it could/should work.
Otherwise it depends on how/if the T is declared in your particular context and you'll need to supply more info.
Anyway, your problem does not seem to be related to autofac in anyway. It's related to the use of generics. The Register method is indeed a generic method, but the generic parameter has to be ultimately translated to a concrete type when the call is made. So, unless T is properly declared in the context of the call to builder.Register then it won't work as it seems you are trying to register a whole range of types.

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.

Categories

Resources