通过下一级服务将参数传递给依赖项

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