Consider the following two classes:
public class Number
{
public int Value { get; set; }
}
public class Multiplier
{
private readonly Number first;
private readonly Number second;
public Multiplier(Number first, Number second)
{
this.first = first;
this.second = second;
}
public int Multiply() => this.first.Value * this.second.Value;
}
The class Multiplier depends on two instances of Number. I want to inject both of them as named services using a DryIoc DI-Container. The code to do this looks like this:
var container = new Container();
container.RegisterInstance(new Number{Value = 2}, serviceKey:"first");
container.RegisterInstance(new Number{Value = 4}, serviceKey:"second");
container.Register<Multiplier>();
var consumer = container.Resolve<Multiplier>();
Console.WriteLine(consumer.Multiply());
This code fails with a DryIoc.ContainerException (when calling Resolve) since the registered instances can not be resolved to the constructor arguments. My question basically is: Is there any way that allows me to specify which named serviceKey should be resolved to which constructor argument?
In MEF I would do the following to achieve this:
[Export(typeof(Multiplier))]
public class Multiplier
{
private readonly Number first;
private readonly Number second;
[ImportingConstructor]
public Multiplier([Import("first")]Number first,
[Import("second")]Number second)
{
this.first = first;
this.second = second;
}
public int Multiply() => this.first.Value * this.second.Value;
}
and then export the dependencies using the service names:
var container = new CompositionContainer(someCatalog);
container.ComposeExportedValue("first", new Number{Value = 2});
container.ComposeExportedValue("second", new Number{Value = 4});
var multi = container.GetExport<Multiplier>();
How can I do this using DryIoc?
First, you may reuse the same MEF code with the DryIoc.MefAttributedModel.dll extension.
With the DryIoc alone, you need to specify the mapping between the parameter name (or Type, or position) and the servicKey
:
var container = new Container();
container.RegisterInstance(new Number {Value = 2}, serviceKey:"first");
container.RegisterInstance(new Number {Value = 4}, serviceKey:"second");
container.Register<Multiplier>(made: Parameters.Of
.Name("first", serviceKey: "first")
.Name("second", serviceKey: "second"));
var consumer = container.Resolve<Multiplier>();
More details here: https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/SpecifyDependencyAndPrimitiveValues.md#complete-example-of-matching-the-parameter-name-to-the-service-key