带有运行时构造函数参数的键控委托工厂?

2024-03-28

假设我有以下服务和组件:

public interface IService
{
    void DoWork();
}

public class ServiceA : IService
{
    private readonly string _name;

    public ServiceA(string name)
    {
        _name = name;
    }

    public void DoWork()
    {
        //ServiceA DoWork implementation
    }
}

public class ServiceB : IService
{
    private readonly string _name;

    public ServiceB(string name)
    {
        _name = name;
    }

    public void DoWork()
    {
        //ServiceB DoWork implementation
    }
}

请注意,每个组件都有一个构造函数参数name。还可以这么说name是在运行时确定的。

我一直在浏览 AutoFac 文档,试图找到一种类型安全的方法来解析此类组件,而无需直接引用容器。如果我只有一个实现IService那么我可以使用代理工厂 https://github.com/autofac/Autofac/wiki/Delegate-Factories将运行时参数传递给构造函数。然而,我有两种实现,应该使用哪一种也必须在运行时确定。如果我没有name构造函数参数然后我可以通过 Key 注册两个组件并使用 Index 解析 https://github.com/autofac/Autofac/wiki/Typed-Named-And-Keyed-Services#by-key

我不知道如何做到这两点。有没有办法以某种方式结合使用委托工厂和IIndex元件分辨率?或者是否有另一种方法可以注册和解析这两个组件,而无需直接引用容器?


正如你所说,你的两个个人AutoFac 本身支持这些要求。

  • 构造函数参数的运行时解析可以使用以下方式实现参数化实例化 http://autofac.readthedocs.org/en/latest/resolve/relationships.html#parameterized-instantiation-func-x-y-b
  • 特定服务实现的解析可以使用以下方式实现键控服务查找 http://autofac.readthedocs.org/en/latest/resolve/relationships.html#keyed-service-lookup-iindex-x-b

然而,似乎没有直接支持同时使用这两个结构。 IE。下列不起作用:

public enum ServiceType
{
    ServiceA,
    ServiceB
}

public class MyComponent
{
    public MyComponent(Func<string, IIndex<ServiceType, IService> factory)
    {
        var service = factory("some_string")[ServiceType.ServiceA];
    }
}

我的工作一直是将服务的解析移至每个服务实现的工厂。然后,其工作原理如下:

  1. 依赖于特定服务实现的组件采用 AutoFac 工厂委托,该委托解析为特定于所需服务实现的工厂
  2. 反过来,服务工厂依赖于 AutoFac 工厂委托,该委托知道如何从服务的(运行时)构造函数参数创建特定的服务实现
  3. 此方法使用本机 AutoFac 构造,并且在容器连接之外不依赖于 AutoFac。

这是一个粗略的例子。请注意,多个工厂可以简化为一个通用工厂 - 但为了清楚起见,我将其保留为原样:

服务实施

public enum ServiceType
{
    NotSet,
    ServiceA,
    ServiceB
}

public interface IService
{
    string DoWork();
}

public class ServiceA : IService
{
    private readonly string _name;

    public ServiceA(string name)
    {          
        _name = name;
    }

    public string DoWork()
    {
        throw new NotImplementedException();
    }
}

public class ServiceB : IService
{
    private readonly string _name;

    public ServiceB(string name)
    {           
        _name = name;
    }

    public string DoWork()
    {
        throw new NotImplementedException();
    }
}

服务工厂

public interface IServiceFactory
{
    IService Create(string name);
}

public class ServiceAFactory : IServiceFactory
{
    private readonly Func<string, ServiceA> _factory;

    public ServiceAFactory(Func<string, ServiceA> factory)
    {            
        _factory = factory;
    }

    public IService Create(string name)
    {
        return _factory(name);
    }
}

public class ServiceBFactory : IServiceFactory
{
    private readonly Func<string, ServiceB> _factory;

    public ServiceBFactory(Func<string, ServiceB> factory)
    {            
        _factory = factory;
    }

    public IService Create(string name)
    {
        return _factory(name);
    }
}

服务注册

builder.RegisterType<ServiceA>().As<ServiceA>();
builder.RegisterType<ServiceB>().As<ServiceB>();
builder.RegisterType<ServiceAFactory>().Keyed<IServiceFactory>(ServiceType.ServiceA);
builder.RegisterType<ServiceBFactory>().Keyed<IServiceFactory>(ServiceType.ServiceB);
builder.RegisterType<ComponentWithServiceDependency>().As<ComponentWithServiceDependency>(); 

用法示例

public class ComponentWithServiceDependency
{
    private readonly IService _service;

    public ComponentWithServiceDependency(IIndex<ServiceType, IServiceFactory> serviceFactories)
    {            
        // Resolve the ServiceB service implementation,
        // using the string "test" as its constructor dependency
        _service = serviceFactories[ServiceType.ServiceB].Create("test");
    }

    public string Test()
    {
        return _service.DoWork();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带有运行时构造函数参数的键控委托工厂? 的相关文章

  • 证书被苹果拒绝

    While configuring certificate for Push Notification on my ios build of cordova project using OneSignal the certificate i

随机推荐

  • 带百分比的虚线圆条

    我正在尝试制作一个带有虚线的圆形进度条 我以编程方式创建stroke dasharray and stroke dashoffset用百分比画一个圆 我需要绘制虚线圆 而不是实心圆 如下所示 我无法将实心圆更改为虚线圆 我是否遗漏了一些东西
  • 使用 C# 中的字典计算字符串中每个重复单词的出现次数[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 编辑 我详细阐述了我的问题更多 解决方案在这里用于修复重复的单词 有人问我每个重复的单词 我是新手 可能不是一个好问题 这是字符串 stri
  • 在屏幕中央显示 Windows 窗体(双屏)

    我有双显示器 想要在屏幕中央显示一个窗口窗体 我有一个变量 MonitorId 0 或 1 I have System Windows Forms Screen allScreens System Windows Forms Screen
  • 解决错误 MSB8011:无法注册输出

    一个奇怪的错误 错误 MSB8011 无法注册输出 请尝试启用每用户 从命令提示符重定向或注册组件 提升的权限 C 程序 文件 MSBuild Microsoft Cpp v4 0 Microsoft CppCommon targets 7
  • Flutter:CupertinoTabBar 在移动到下一个屏幕时不会消失

    我正在运行 Google 的 Flutter Gallery 示例 https github com flutter flutter blob master examples flutter gallery lib demo cuperti
  • Angularjs 1.5 组件模式,带有回调函数,由 IE11 中的嵌入对象多次调用,不更新 Angular 绑定

    在 IE 11 中 我有一个 Angularjs 1 5 模态组件 如下所示 模式打开 在渲染事件中 它使用该组件中包含的回调函数调用角度应用程序外部的函数 这个外部函数启动一个安装过程 启动一个嵌入对象 如下所示 然后定期调用回调函数 我
  • 如何获取Spring事务管理器实例?

    我使用注释来标记应在事务中执行的方法 但是 在一个地方我需要做transactionManager rollback 手动 无注释 我怎样才能获得transactionManager object 如果你想回滚当前事务 你可以使用 Tran
  • 注释正则表达式

    我正在尝试在 JavaScript 中注释正则表达式 似乎有很多关于如何remove使用正则表达式的代码注释 但实际上不是如何commentJavaScript 中的正则表达式因此更容易理解 不幸的是 JavaScript 没有像其他语言那
  • 当缓冲区有未保存的更改且未命名时退出 vim?

    我在 vim 中创建了一个空白的 临时缓冲区 即不与特定文件关联 方法是使用 vnew 然后我玩了一些文本 现在我只想退出编辑器 不保留这个 临时缓冲区 的内容 当我输入命令时 q Vim 给我 No Name E37 No write s
  • 如何增加 Angular UI Bootstrap 中的模式宽度?

    我正在创建一个模式 var modal modal open templateUrl partials welcome controller welcomeCtrl backdrop static scope scope 有没有办法增加它的
  • 如何在vuejs中的输入文本中添加禁用属性?

    我有2个网址 register register sponsor 4 The register路线会给我一个干净的输入文本 我可以在其中输入所有内容第二条路由将带来相同的输入 但其值为 4 并且已禁用 因此用户无法修改它 我设法使用 vue
  • Mapbox GL JS:将基础层设置为白色?

    我想显示带有白色背景的 Mapbox GL JS 地图 而不是地图背景 这是我现在的代码 mapboxgl accessToken mytoken var map new mapboxgl Map container map style m
  • 每分钟有多少个请求被视为“重负载”? (近似)

    人们经常在他们的 优化和性能相关 问题和答案中谈论 重负载 我试图在典型服务器上的常规 Web 应用程序的上下文中 以 SO 及其相当小的基础设施为例 以每分钟的请求数来量化这一点 假设它们立即返回 以简化并获取数据库速度 等式之外 我正在
  • Android 自定义 EditText 在 ICS 中不显示光标

    我的应用程序中有一个 EditText 它仅接收来自我放置在屏幕上的按钮的输入 为了避免出现软键盘 我有一个自定义的 EditText 类 如下所示 public class CustomEditText extends EditText
  • “不为空”和“不为空”有什么区别

    SELECT id FROM customers WHERE type IS NOT Null Versus SELECT id FROM customers WHERE NOT type IS NULL 上述任何一个返回的数据都将完全相同
  • sp_getapplock 无事务

    我正在实现内部没有事务的存储过程 事实上 它会 但仅限于特定地点 以将时间减少到最少 存储过程的本质是我一次只想运行一个 我尝试使用 sp getapplock 但很快发现它需要在事务内部 是否有其他选择可以在整个过程上锁定但不将其包装到事
  • 没有为类型“QuerySnapshot”定义 getter“文档”

    尝试从 Firestore 实时数据库访问数据 但我一直收到此消息和其他几条消息 在这种情况下我该如何访问数据 先感谢您 class HomePage extends StatefulWidget override HomePageStat
  • 如何在不单击表单的情况下触发表单上的默认按钮(winforms)?

    我有两个文本框 一个用于登录 ID 另一个用于密码 并且有一个按钮 提交 我需要一个获取登录 ID 和密码值的事件 即 无需单击鼠标 我需要调用此事件 只需按键盘上的 输入 即可 有谁能够帮助我 提前致谢 斯里尼 将按钮设置为表单上的接受按
  • 格式化 NumPy 数组

    我要这个 SP 1 2 3 1 1 000000e 00 2 000000e 00 3 000000e 00 2 1 630000e 01 1 990000e 01 1 840000e 01 3 1 630000e 01 1 990000e
  • 带有运行时构造函数参数的键控委托工厂?

    假设我有以下服务和组件 public interface IService void DoWork public class ServiceA IService private readonly string name public Ser