Kyr*_*o M 3 c# design-patterns dependency-injection factory-pattern
我的项目已包含一些处理程序的工厂(代码非常简化):
class HandlersFactory
{
private static readonly Dictionary<string, IHandler> registeredHandlers =
new Dictionary<string, IHandler>
{
{ "First", new FirstHandler() },
{ "Second", new SecondHandler() },
{ "Third", new ThirdHandler() },
};
public bool IsRegisteredHandler(string name)
{
return registeredHandlers.ContainsKey(name);
}
public IHandler GetHandler(string name)
{
if (!IsRegisteredHandler(name))
return null;
return registeredHandlers[name];
}
}
Run Code Online (Sandbox Code Playgroud)
处理程序列表是硬编码的.工厂位于主程序集中,但应用程序可以在运行时使用其他程序集进行扩展(主应用程序搜索它们并在开始时加载).附加组件定制应用程序
必须有可能从主程序集中"替换"一些处理程序(提供另一个逻辑).因此,例如,工厂将按CustomSecondHandler名称"Second" 返回,而不是SecondHandler在加载其他程序集时返回.我能够重写工厂,但更改不得影响已经使用它的代码.
我想过将字典初始化移动到RegisterHandlers可以在自定义工厂中重写的某些方法.并添加工厂的依赖注入,因此附加组件提供从现有工厂派生的工厂自己的实现.如果未加载其他程序集,则使用默认工厂.但我觉得这种方法有问题.
请提出你的想法.我需要一个干净的解决方案,只需要最少的代码编写,以提供将取代现有的自定义处理程序
谢谢.
如何扫描这些处理程序的程序集?如果使用反射,则可以使用自定义属性.考虑:
[ForcesHandlerRegistrationOverride]
public class CustomSecondHandler : IHandler
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
我假设您有办法为加载的处理程序生成正确的字典键以及创建处理程序实例 - 跳过这些部分(name和handler变量初始化),这里是程序集扫描的样子:
var types = loadedAssembly
.GetTypes()
.Where(t => type.IsAssignableFrom(typeof(IHandler)));
foreach (var type in types)
{
if (factory.IsRegisteredHandler(name))
{
// usually you'll do nothing here, but now we check if handler
// we want to register is marked with custom attribute so that
// we can override already registered handler
var canForceOverride = type.GetCustomAttributes(
typeof(ForcesHandlerRegistrationOverride), true).Length > 0;
if (canForceOverride)
{
factory.RegisterHandler(name, handler);
// ...or to keep this one safe, add more appropriate method
// for explicit replacement (see note below)
}
}
else
{
factory.RegisterHandler(name, handler);
}
}
Run Code Online (Sandbox Code Playgroud)
如果您的工厂类的注册方法以某种方式防止将处理程序添加到已存在的键两次,那么您可能必须摆脱它(或者公开可以替换处理程序的注册方法;比如ReplaceHandler或ForceRegistration).
这样您就可以轻松控制何时类型应覆盖/替换现有处理程序,或者只是注册为新处理程序.
请注意,您甚至可以更进一步; 使用应该替换的处理程序名称声明属性 - [ForcesHandlerRegistrationOverride("Second")].
| 归档时间: |
|
| 查看次数: |
809 次 |
| 最近记录: |