1 回答
TA贡献1942条经验 获得超3个赞
考虑到问题评论,我建议有一个IStrategy接口并用于IEnumerable<Func<IStrategy>>注入策略工厂列表(这里为了简洁起见我使用委托工厂,可以使用接口代替)。因此,我们可以将创建这样一个列表与创建策略脱钩:
static IEnumerable<IStrategy> CreateAll(this IEnumerable<Func<IStrategy>> factories) =>
factories.Select(factory => factory());
使用示例:
listOfStrategies.AddRange(
new Func<IStrategy>[]
{
() => new B(),
() => new C()
}).CreateAll()); // 2 items (`B` and `C`) will be added.
Func<IStrategy>如果方便的话,可以从类层次结构中创建策略工厂列表 ( ):
static IEnumerable<Func<IStrategy>> GetByBaseType<T>() =>
typeof(T)
.Assembly
.GetTypes()
.Where(t => t.IsSubclassOf(typeof(T)) && t.GetInterface(nameof(IStrategy)) != null)
// We assume t has a parameterless constructor
.Select(t => (Func<IStrategy>)(() => (IStrategy)Activator.CreateInstance(t)));
一个样品:
class A { }
class B : A, IStrategy { }
class C : A, IStrategy { }
创建策略工厂列表:
var factories = GetByBaseType<A>().ToList(); // Two `Func<IStrategy>` objects
var strategies = CreateAll(factories).ToList(); // Two `IStrategy` objects - `B` and `C`.
此外,通常返回的方法比接受并向其中添加项目的IEnumerable<T>方法更具可重用性和“纯粹”性。List<T>
还有一件事 - 许多 DI 容器支持解析所有已注册实现的列表。请参阅UnityContainer下面的示例:
var c = new UnityContainer()
.RegisterType<IStrategy, B>("B")
.RegisterType<IStrategy, C>("C");
// Two items - `B` and `C`.
c.Resolve<IEnumerable<IStrategy>>().ToList();
- 1 回答
- 0 关注
- 102 浏览
添加回答
举报