通过IOC容器使用工厂解决处理程序
-
21-12-2019 - |
题
我有重构单片MVC应用程序的任务(1多个线缆,超过1000线)进入更可管理的东西。
程序的目的是以特定顺序解析不同类型的集合,一个接一个地。
这是一个提出的“更好”解决方案的示例...
public interface IFruit
{
}
public class Banana : IFruit
{
}
public class Apple : IFruit
{
}
public interface IFruitHandler<in TFruit> where TFruit : IFruit
{
void Handle(IEnumerable<TFruit> fruit);
}
public class BananaHandler : IFruitHandler<Banana>
{
public void Handle(IEnumerable<Banana> fruit)
{
Console.WriteLine("break apart the bunch of bananas");
foreach (var banana in fruit)
{
Console.WriteLine("Peel the banana");
}
}
}
public class AppleHandler : IFruitHandler<Apple>
{
public void Handle(IEnumerable<Apple> fruit)
{
foreach (var apple in fruit)
{
Console.WriteLine("Slice the apple");
}
Console.WriteLine("Throw the apple cores away");
}
}
.
正如您所看到的,每个水果都有自己的处理程序,并且每个处理器实现可能略有不同。 一些处理程序在通过收集之前做的事情,其他人之后做事,在之前和之后做的一些事情。
应用程序呈现一个对象(通过MVC控制器),所有不同的水果集合作为属性(基本上是一个大视图模型)。我想要一些可以采取所有这些系列的调解员并将它们传递给适当的处理程序。
这就是我想到的...
public class Mediator : IMediator
{
private readonly Func<Type, IFruitHandler<IFruit>> handlerFactory;
public Mediator(Func<Type, IFruitHandler<IFruit>> handlerFactory)
{
this.handlerFactory = handlerFactory;
}
public void Execute(IEnumerable<IEnumerable<IFruit>> fruitBundles)
{
foreach (var bundle in fruitBundles)
{
if (!bundle.Any())
continue;
var handler = handlerFactory(bundle.First().GetType());
handler.Handle(bundle);
}
}
}
.
水果束将始终包含一个水果,并且捆绑包将以特定的顺序。 Mediator.execute的签名足够松散,以便一个捆绑包含有不同的水果。这不应该发生。
问题是两倍....
我可以用OpenGenerics注册所有Fruithandler ...
container.RegisterManyForOpenGeneric(typeof(IFruitHandler<>),typeof(IFruitHandler<>).Assembly);
.
但我遇到困难为工厂进行注册正确 - 如何使用简单的注射器注册工厂?
介质/处理器工厂实施感觉尴尬,IFRuit接口(其有效只是一个标记) - 你会改变设计吗?
解决方案
您可以以下列方式实现Mediator
,但它有一些缺点:
-
它使用
-
Mediator
需要引用Container
(尽管如果您在组合根中定义此类),但如果您在组成根中定义此类))
dynamic
我觉得这个问题太普遍,无法以更好的方式提供任何具体建议来设计解决方案。
class Mediator : IMediator
{
private readonly Container container;
public Mediator(Container container)
{
this.container = container;
}
public void Handle(IEnumerable<IEnumerable<IFruit>> fruitBundles)
{
foreach (var bundle in fruitBundles)
{
if (bundle.Any())
{
dynamic instance = bundle.First();
this.Handle(instance, bundle);
}
}
}
private void Handle<T>(T instance, IEnumerable<IFruit> bundle)
where T : IFruit
{
var handler = this.container.GetInstance<IFruitHandler<T>>();
handler.Handle(bundle.Cast<T>());
}
}
. 不隶属于 StackOverflow