Prism可以使用.NET Core内置的依赖注入吗?

2024-01-10

我想使用 .NET Core 3.1 启动 WPF 应用程序
Prism可以利用.Net Core的内置DI(IServiceCollection)或者我必须使用Unity之类的东西吗?
如果Prism不能使用内置DI,它们可以并存吗?


Prism可以利用.Net Core内置的DI吗

据我所知,您无法真正用 ASP.NET Core 内置工具替换 Prism 的 DryIot。主要是 DryIot 比 ServiceCollection API 功能更齐全。有这个开源的package https://github.com/dansiegel/Prism.Container.Extensions/tree/master/src/Prism.Microsoft.DependencyInjection.Extensions我发现有一个IContainerExtension实施使用ServiceCollection,但根据开发人员自己的说法,这更多的是概念验证而不是可靠的解决方案。

如果Prism不能使用内置DI,它们可以并存吗?

是的他们可以。需要注意的是 - 您不能简单地在ServiceCollection并期望能够将该服务直接注入您的应用程序、模块和视图模型中。这将失败,因为这些文件由 Prism 框架管理,因此注入仅适用于您使用IContainerRegistry界面。

Benefits

你为什么要这么做?作为内置的物联网容器ServiceCollectionAPI 是众所周知的,因此对于 .Net 开发人员来说会更简单。此外,您可以构建非 WPF 项目以使用默认容器注册服务,从而使它们与您的桌面项目完全解耦。这对于领域驱动设计等更复杂的架构非常有用。

让我们考虑以下项目结构:

solution
-- Desktop // Prism WPF application, containing only views and models
-- Application // Class library, containing operational logic.

假设作为应用程序项目的一部分,您需要一个IUserService它保存有关当前用户的信息,当用户在桌面应用程序中进行身份验证时,必须将这些信息填充到内存中。注册方法如下所示:

public IServiceCollection AddServices(this IServiceCollection services)
{
    services.AddSingleton<IUserService, UserService>()
}

所以现在我们需要将它注入到桌面项目中。我建议两种方法:

  1. Simple
  2. Seemless

Simple

这种方法需要非常简单的启动配置。需要注意的是,您将无法直接在构造函数中注入服务,而是通过IServiceProvider界面。

  1. 参考Microsoft.Extensions.DependencyInjection

  2. 在App中调用您的服务注册方法:

     protected override void RegisterTypes(IContainerRegistry container)
     {
         // Build service provider using the ServiceCollection API
         var provider = new ServiceCollection()
             .AddServices()
             .BuildServiceProvider();
    
         // Register IServiceProvider within DryIot and provide 
         // a factory method to retrieve the service instance
         container.Register<IServiceProvider>(() => provider);
     }
    
  3. Inject IServiceProvider在你需要的地方IUserService。在本例中,我将使用 Prism 模块:

     public class Module : IModule
     {
         private readonly IUserService userService;
    
         public Module(IServiceProvider serviceProvider)
         {
             this.userService = serviceProvider.GetService<IUserService>();
         }
         ...
         private void Authenticate()
         {
             this.userService.IsAuthenticated = true;
         }
     }
    

就是这样,您现在可以在任何可以访问的地方使用 ServiceCollection 注册的依赖项IServiceProvider通过棱镜注入。这是我推荐的方法,因为我们只是将 .Net 容器包装在 Prism 中。

Seemless

这就是事情变得更有趣的地方。完整免责声明 - 使用此方法可能会遇到问题。除了最基本的用例之外,我还没有对此进行测试。此方法提供的唯一优点是您将能够直接在构造函数中注入服务,而不必通过IServiceProvider.

从本质上讲,该方法只是循环ServiceCollection并直接在 Prism 容器中注册所有服务。如果我们看一下实施ServiceCollection- 这只是一个列表ServiceDescriptors。经过进一步检查,我们发现ServiceDescriptior包含一堆构造函数。我们将忽略这些并专注于属性:

  1. ServiceType- 注入时将使用的类型
  2. ImplementationType- 要注入的实现类型
  3. ImplementationInstance- 实现类型的实例
  4. ImplementationFactory- 返回实现类型实例的工厂委托
  5. LifeTime- Singleton、Scoped 或 Transient 类型

现在让我们检查一下IContainerRegistry界面。我们会看到有很多重载Register接受类型、对象和委托。

利用这些知识,我们现在可以创建一个适配器ServiceDescriptor到注册IContainerRegistry。下面的实现仅关注瞬态服务,但服务生命周期之间的区别只是我们调用哪种注册表方法 -Register对于瞬态和RegisterSingleton对于单身人士来说。

  1. 使用接受的静态方法创建适配器类IContainerRegistry and ServiceDescriptor论点:

     public static void Register(IContainerRegistry container, ServiceDescriptor service)
     {
         // In case an implementation instance is provided we simply need to register it
         if (service.ImplementationInstance != null)
         {
             containter.Register(service.ServiceType, service.ImplementationInstance);
         }
         // In case a factory is provided we have a bit more work. 
         // We need to modify it in order for it to be usable by the DryIot container
         else if (service.ImlementationFactory != null)
         {
             var factory = service.ImplementationFactory;
             var dryIotFactory = dryIotProvider =>
             {
                 var provider = dryIotProvider.Resolve<IServiceProvider>();
                 return factory(provider);
             };
    
             container.Register(service.ServiceType, dryIotFactory);
         }
         // If no implementation or factory is provided then we simply register the
         // types and let the container create the implementation instance on its own.
         else
         {
             container.Register(service.ServiceType, service.ImplementationType);
         }
     }
    

这里最棘手的部分是工厂。为了更好地理解服务注册中的工厂,有时您可能需要访问其他服务才能提供正确的实现实例。例如如果IHttpClient已注册您需要提供IAuthorizationSerice with HttpAuthorizationService实施而不是DesktopAuthorizationService.

本质上,我们用一个与 DryIot 兼容的工厂(接受 DryIot 容器的实例)包装原始工厂方法,该工厂可以为原始工厂提供IServiceProvider实例。

  1. 参考Microsoft.Extensions.DependencyInjection

  2. 在App中调用您的服务注册方法:

     protected override void RegisterTypes(IContainerRegistry container)
     {
         var services = new ServiceCollection().AddServices()
    
         foreach (var service in services)
         {
             Adapter.Register(container, service);
         }
     }
    
  3. Inject IUserService直接在模块构造函数中:

     public class Module : IModule
     {
         private readonly IUserService userService;
    
         public Module(IUserService userService)
         {
             this.userService = userService;
         }
     }
    

最后的想法

我再次推荐简单的方法。简单意味着较低的学习曲线和较小的错误空间。相比之下,带来的不便就很小了。

另一个公平的警告 - 这不是生产就绪的代码。尤其是无痕法。我还没有对这个实现进行“战斗测试”,但它可能会为您指明正确的方向。

如果有人有反馈/意见,我很乐意阅读:)

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

Prism可以使用.NET Core内置的依赖注入吗? 的相关文章

随机推荐

  • opencv中有没有相当于matlab conv2的函数

    matlab函数conv2有直接的opencv函数吗 我尝试使用 cvFilter2D 但它似乎给出了与 conv2 不同的结果 例如 CvMat Aa cvCreateMat 2 2 CV 32FC1 CvMat Bb cvCreateM
  • 如何在R中按两列进行分组

    我有一个数据框 我试图对其进行分组 然后根据两列求和 两列是字符 其中一列是月份 另一列是变量 以下是数据框架和结构的示例 row names month variable amount 1 1 Jan x 1000 2 1 Jan x 3
  • 在R中将两列合并为一列[重复]

    这个问题在这里已经有答案了 我有以下数据框 并尝试将两列合并为一列 同时替换NA与数值 ID A B 1 3 NA 2 NA 2 3 NA 4 4 1 NA 我想要的结果是 ID New 1 3 2 2 3 4 4 1 提前致谢 在编写答案
  • 在 pyspark databricks 中并行执行多个笔记本

    问题很简单 master dim py calls dim 1 py and dim 2 py并行执行 这在 databricks pyspark 中可能吗 下图解释了我想要做什么 由于某种原因它出错了 我在这里遗漏了什么吗 仅供其他人使用
  • npm install:使用全局包(如果存在),而不是安装两次

    使用时npm install with a package json文件 如何让它使用符合条件的全局安装的软件包 而不是再次在本地下载并安装该软件包 我知道关于link https docs npmjs com cli link 但是有办法
  • java除法运算中Nan和Infinity是由什么决定的

    下面代码的输出让我感到困惑 为什么NaN有时是无穷大 有时是无穷大 public static void main String args double a 0 0 double b 1 0 int c 0 System out print
  • MySQL 存储过程通过 MS Access (VBA) 中的 ADODB 的输出参数在一台计算机上正确,在另一台计算机上随机

    我已经尝试了 几乎 一切方法来隔离问题 但我迷失了 我有一个 MS Access 应用程序 它使用 ADODB 连接到本地 MySQL 数据库 我将其复制到一台新计算机 但现在存储过程的输出参数每次都包含一个随机值 如果通过 ADODB 完
  • 你能用C#制作一个alpha透明的PNG吗?

    我有一个显示垂直文本的多浏览器页面 作为让文本在所有浏览器中垂直呈现的丑陋黑客 我创建了一个自定义页面处理程序 它返回一个带有垂直绘制文本的 PNG 这是我的基本代码 C 3 但对任何其他版本进行了小幅更改 直至 1 Font f GetS
  • 流星: 发送电子邮件 | AuthError:登录无效 - 535-5.7.8

    我已经安装了电子邮件包并尝试发送测试邮件 但它向我显示以下错误 AuthError 无效登录 535 5 7 8 用户名和密码不被接受 我确信凭据是正确的 并且代码与以下内容相同 https github com ideaq meteor
  • 滚动捕捉会跳过较小屏幕上的部分 - Chrome

    我正在尝试在页面上实现滚动捕捉 我已将scroll snap type 添加到容器元素 并将scroll snap align 添加到子部分 它在大屏幕上的 Chrome 上运行良好 在所有屏幕尺寸的 Firefox 上运行良好 然而 它似
  • 如何从 JTable 中删除一行? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我想从 JTable 中删除一些行
  • 利用浏览器缓存外部文件

    我试图让我的谷歌页面速度洞察评级达到不错的水平 但是我也想缓存一些外部文件 有人知道处理这个问题的最佳方法是什么吗 https s swiftypecdn com cc js 5 minutes https pagead2 googlesy
  • 如何使用python比较两个球点的大圆距离和欧氏距离?

    我试图检查当您使用欧几里德距离而不是使用大圆距离 gcd 计算地球上两点的距离时引入的错误 我有两个由纬度和经度定义的点 我使用了 python geopy 框架大圆距离 https github com geopy geopy blob
  • Unity Animator SetTrigger 未重置为默认值

    正如我希望正确理解动画器 SetTrigger 一旦完成就会将动画设置为 false 如果我错了请纠正我 但我的项目并非如此 我有两种状态 默认 不执行任何操作 和移动 打开应用程序时会自动输入默认值 并且当我调用 SetTrigger 时
  • 获取 GIF 图像的第一帧而不下载所有其他帧

    我想从网络上获取一张GIF图像 但我发现如果我下载整个GIF图像 会导致大量的网络流量 我可以只获取 GIF 图像的第一帧而不下载所有其他帧吗 9 年零 6 个月后 正是伸出援手的最佳时机 这可以使用 ImageMagick 使用以下命令来
  • 离子服务/离子运行不反映变化

    ionicserve 和 ionicrun 都没有反映我的任何最新更改 ionicserve 显示了几个小时前的情况 ionicrun 显示了大约一个小时后的情况 从那时起 我放弃了所有更改 并从父分支创建了一个新分支 但它仍然在第一个分支
  • 如何以守护进程模式运行 Django 服务器?

    我想在守护进程模式下运行 Django 开发服务器 这样当我退出 shell 时 服务器仍然会运行 我怎样才能做到这一点 除了 Bernhard 所说的之外 如果您计划将其用于生产环境 您应该使用 mod wsgi 在 apache 下运行
  • 当用户滚动到页面最底部时淡入/淡出固定位置 div

    这看起来相当简单 但我试图让固定位置的页脚 div 在用户滚动到网页最底部时滑动并淡入 然后在用户向上滚动时滑动并淡出 我搜索了 Stack Overflow 其他人提出了建议的解决方案 但我的代码导致我的 div 只能滑动和淡入 当用户向
  • 我的数据库没有更新,如果我的JSON数据也会增加

    我正在将 JSON 数据解析到数据库 该数据显示在我的 lisview 中 但是第一次它从我的 JSON 获取数据并将其存储在数据库中 如果我在网站中添加任何内容 它不会升级 json 也会增加 但不会增加反映在数据库中 数据库部分也没有升
  • Prism可以使用.NET Core内置的依赖注入吗?

    我想使用 NET Core 3 1 启动 WPF 应用程序Prism可以利用 Net Core的内置DI IServiceCollection 或者我必须使用Unity之类的东西吗 如果Prism不能使用内置DI 它们可以并存吗 Prism