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

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

必须有可能用新的“替换”主程序集中的一些处理程序(提供另一种逻辑)。因此,例如工厂将返回 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# - 使用 WPF 向外部应用程序发送 Enter 键时出现问题

c# - 可以处理错误的组件的异常或返回状态

design-patterns - "Chain of responsibility"和 "Strategy"模式有什么区别?

c# - 在这种情况下如何不使用 DependencyResolver.Current.GetService(...)

javascript - 当它们属于同一个模块时,如何将 nestjs 服务注入(inject)另一个服务?

c# - GameObject.FindGameObjectsWithTag()无法正常工作

c# - wpf 中的 MVVM 模式 - 一个数据模型,多个 View 模型

javascript - 在 WebBrowser 控件中检测滚动到底部

java - 设计通用纸牌的单例类?

c# - 存储库模式是如何真正完成的?