c# - 具有依赖注入(inject)设计的处理程序工厂

标签 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];
    }
}

处理程序列表是硬编码的。工厂位于主程序集中,但应用程序可以在运行时使用其他程序集进行扩展(主应用程序搜索它们并在启动时加载)。附加组件定制应用程序。

必须有可能用新的处理程序“替换”主程序集中的某些处理程序(提供另一种逻辑)。因此,例如,当加载附加程序集时,工厂将返回名称为“Second”的 CustomSecondHandler,而不是 SecondHandler。我可以重写工厂,但更改不得影响已经使用它的代码。

我考虑过将字典初始化移动到可以在自定义工厂中覆盖的某些方法 RegisterHandlers 中。并添加工厂的依赖注入(inject),因此额外的程序集提供了从现有工厂派生的自己的工厂实现。如果未加载其他程序集,则使用默认工厂。但我觉得这种做法有问题。

请提出您的想法。我需要一个代码编写最少的干净解决方案,以提供将替换现有处理程序的自定义处理程序。

谢谢。

最佳答案

您如何扫描您的程序集以查找这些处理程序?如果你使用反射,你可以利用 custom attributes .考虑:

[ForcesHandlerRegistrationOverride]
public class CustomSecondHandler : IHandler
{
    // ...
}

我假设您有办法为加载的处理程序生成正确的字典键以及创建处理程序实例 - 跳过这些部分(namehandler 变量初始化),这里是程序集扫描可能是什么样子:

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);
    }
}

如果您在工厂类上的注册方法以某种方式防止将处理程序添加到已存在的 key 两次,您可能必须摆脱它(或公开可以替换处理程序的注册方法;像 ReplaceHandlerForceRegistration)。

这将使您可以轻松地控制您的类型何时应该覆盖/替换现有的处理程序,或者简单地注册为新的处理程序。

请注意,您甚至可以更进一步;使用应该替换的处理程序名称声明您的属性 - [ForcesHandlerRegistrationOverride("Second")]

关于c# - 具有依赖注入(inject)设计的处理程序工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9609767/

相关文章:

c++ - 单例设计模式中复制构造函数和赋值运算符的使用

java - 在Java中,如何实现类似使用模板参数的功能,避免在C++中创建Creator子类?

java - 处理继承时删除条件语句

c# - 温莎城堡 : Register by Convention with Named part

c# - 使用带有 Umbraco Controller 的简单注入(inject)器

java - 什么是依赖注入(inject)和 Spring 框架?

javascript - ASP.NET AJAX 控件工具包文件上传在 Scriptresource.axd 中引发错误

c# - gtk# ScrolledWindow - 滚动到顶部

c# - 使用 C# 下载 Windows 更新

c# - SalesForce Web 服务 - 请求元素未被识别