I understand how to resolve a named parameter if I resolve exactly that service which has that parameter. But the thing is that in my case I have such service as a dependecy. Here is the example:
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Dependency>();
builder.RegisterType<Something>();
var container = builder.Build();
container.Resolve<Dependency>(new NamedParameter("prm", "test"));
container.Resolve<Something>(new NamedParameter("prm", "test")); //Fails
}
}
class Dependency
{
public Dependency(string prm) { }
}
class Something
{
public Something(Dependency dep) { }
}
It fails on the second Resolve call but I need something like this. Could you please advise something to solve it? Maybe I shoud mark the parameter to be something like this:
container.Resolve<Something>(new NamedParameter<Dependency>("prm", "test"));
This is how I fixed my particular problem. It supports both dynamic (run-time) and static (compile-time) values:
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<Dependency2>();
builder.RegisterGeneric(typeof(SomethingFactory<>));
builder.RegisterType<Something>().WithAttributeFiltering();
var container = builder.Build();
Console.WriteLine(container.Resolve<Something>()
.GetPrm());
Console.WriteLine(container.Resolve<SomethingFactory<Something>>()
.GetService(new Dependency1("My test value from the factory")).GetPrm());
Console.WriteLine("But the registration is " + container.IsRegistered<Dependency1>());
}
}
class Dependency1
{
private readonly string _prm;
public Dependency1(string prm) => _prm = prm;
public string GetPrm() => _prm;
}
class Dependency2
{
private readonly Dependency1 _dep;
public Dependency2(Dependency1 dep) => _dep = dep;
public string GetPrm() => _dep.GetPrm();
}
class Something
{
private readonly Dependency2 _dep;
public Something([Prm("My test value from the attribute")]Dependency2 dep) => _dep = dep;
public string GetPrm() => _dep.GetPrm();
}
class Prm : ParameterFilterAttribute
{
private readonly string _prm;
public Prm(string prm) => _prm = prm;
public override bool CanResolveParameter(ParameterInfo parameter, IComponentContext context)
=> !context.IsRegistered<Dependency1>();
public override object ResolveParameter(ParameterInfo parameter, IComponentContext context)
{
if (parameter == null)
{
throw new ArgumentNullException(nameof(parameter));
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var container = context.Resolve<ILifetimeScope>();
using var scope = container.BeginLifetimeScope(builder
=> builder.RegisterInstance(new Dependency1(_prm)));
return scope.Resolve(parameter.ParameterType);
}
}
class SomethingFactory<T>
{
private readonly ILifetimeScope _container;
public SomethingFactory(ILifetimeScope container)
{
_container = container;
}
public T GetService(Dependency1 dep)
{
if (dep == null)
{
throw new ArgumentNullException(nameof(dep));
}
using var scope = _container.BeginLifetimeScope(builder => builder.RegisterInstance(dep));
return scope.Resolve<T>();
}
}
My test value from the attribute
My test value from the factory
But the registration is False