通过下一级服务将参数传递给依赖项
Passing parameters to dependencies through a next level service
如果我准确解析具有该参数的服务,我明白如何解析命名参数。但问题是,就我而言,我有这样的服务作为依赖。这是示例:
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) { }
}
它在第二次 Resolve 调用时失败,但我需要这样的东西。你能建议一些东西来解决它吗?也许我应该将参数标记为如下所示:
container.Resolve<Something>(new NamedParameter<Dependency>("prm", "test"));
这就是我解决特定问题的方法。它同时支持动态(运行-time)和静态(编译时)值:
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
如果我准确解析具有该参数的服务,我明白如何解析命名参数。但问题是,就我而言,我有这样的服务作为依赖。这是示例:
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) { }
}
它在第二次 Resolve 调用时失败,但我需要这样的东西。你能建议一些东西来解决它吗?也许我应该将参数标记为如下所示:
container.Resolve<Something>(new NamedParameter<Dependency>("prm", "test"));
这就是我解决特定问题的方法。它同时支持动态(运行-time)和静态(编译时)值:
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