【问题标题】:DryIoC pass param to constructor of open generic service based on generic type parameterDryIoC 将参数传递给基于泛型类型参数的开放泛型服务的构造函数
【发布时间】:2020-12-13 06:22:26
【问题描述】:

假设我有这个服务和两个策略:

public class SomeService<TEntity> : ISomeService<TEntity>
{
    public SomeService(ICurrentDbContext context, IStrategy<TEntity>? delete = null)
         : base(context, delete ?? new DefaultStrategy<TEntity>())
        {}
}

public class DefaultStrategy<TEntity> : IStrategy<TEntity> {}

public class CustomStrategy<TEntity> : IStrategy<TEntity> {}

我当前的服务注册如下:

container.Register(typeof(ISomeService<>), typeof(SomeService<>), Reuse.Transient);

我想在这里实现的是如果泛型类型参数 T 实现了某个接口,例如 IFoo.否则,将其保留为默认值为 null 的参数。

在这两种情况下,第一个参数都应该被自动解析为已注册的依赖项。

暂时不知道该怎么做,我应该使用拦截器吗?

【问题讨论】:

    标签: generics dryioc


    【解决方案1】:

    你可以这样做(但你的问题并不清楚为什么你有两种策略DefaultStrategy&lt;TEntity&gt;CustomStrategy&lt;TEntity&gt;)。

    using System.Linq;
    using NUnit.Framework;
    
    namespace DryIoc.IssuesTests
    {
        [TestFixture]
        public class SO_DryIoC_pass_param_to_constructor_of_open_generic_service_based_on_generic_type_parameter
        {
            [Test]
            public void Test()
            {
                var container = new Container();
    
                container.Register(typeof(ISomeService<>), typeof(SomeService<>), Reuse.Transient,
                    made: Parameters.Of.Details((req, p) => 
                        p.ParameterType.GetGenericDefinitionOrNull() == typeof(IStrategy<>) && 
                        p.ParameterType.GetGenericParamsAndArgs().Any(x => x.IsAssignableTo<IFoo>())
                        ? null                              // the default injection behavior 
                        : ServiceDetails.Of(value: null))   // otherwise return the `null` value
                    );
    
                container.Register<ICurrentDbContext, MyDbContext>();
                container.Register(typeof(IStrategy<>), typeof(DefaultStrategy<>));
    
                var s1 = container.Resolve<ISomeService<OtherEntity>>();
                Assert.IsNull(((SomeService<OtherEntity>)s1).Delete);
    
                var s2 = container.Resolve<ISomeService<FooEntity>>();
                Assert.IsNotNull(((SomeService<FooEntity>)s2).Delete);
            }
    
            public interface ISomeService<TEntity> {}
            public class SomeService<TEntity> : ISomeService<TEntity>
            {
                public readonly IStrategy<TEntity> Delete;
                public SomeService(ICurrentDbContext context, IStrategy<TEntity> delete = null) => Delete = delete;
            }
    
            public interface IFoo {}
            public class FooEntity : IFoo {}
    
            public class OtherEntity {}
    
            public interface IStrategy<TEntity> {}
            public class DefaultStrategy<TEntity> : IStrategy<TEntity> { }
            public class CustomStrategy<TEntity> : IStrategy<TEntity> { }
    
            public interface ICurrentDbContext {}
            public class MyDbContext : ICurrentDbContext {}
        }
    }
    
    

    【讨论】:

    • 感谢您的回答。看起来像我一直在寻找的东西。 Unfotenetly 当我应用该规则时,我将第一个参数 ICurrentDbContext 设为空。关于您的问题-假设我有一些由接口标记的实体,表示我需要使用一个服务,该服务通过一些自定义策略为其提供处理逻辑;否则(对于所有未标记的实体,我需要使用具有默认行为的策略)。如果您需要更多详细信息,我将提供一个真实的示例。
    • 解决了!非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多