Unity 与 ASP.NET Core 和 MVC6(核心)

2024-03-25

更新 09.08.2018
Unity正在开发中here https://github.com/unitycontainer/container但我还没有时间测试它如何与 ASP.NET Core 框架配合使用。

更新 15.03.2018
此解决方案针对在使用 .NET Framework 4.5.2 时将 ASP.NET Core v1 与 Unity 结合使用的特定问题NOT.NET 核心框架。我必须使用此设置,因为我需要一些 .Net 4.5.2 DLL,但对于任何重新开始的人,我不会推荐此方法。而且 Unity 没有进一步开发(据我所知),因此我建议在新项目中使用 Autofac 框架。看到这个Post https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection#replacing-the-default-services-container有关如何执行此操作的更多信息。

Intro
我正在使用 ASP.NET 和 MVC 构建 Web 应用程序。此应用程序依赖于某些服务(WCF 服务、数据存储服务等)。现在,为了保持良好的状态和解耦,我想使用 DI(依赖注入)框架,特别是 Unity。

初步研究
我找到了这个博客文章 http://www.global-webnet.com/blog/post/2015/08/24/Dependency-Injection-in-ASPNET-vNext-(adding-Unity-container).aspx但遗憾的是它不起作用。不过这个主意不错。
它基本上是说,您不应该将 ServiceCollection 中注册的所有服务注册到您自己的容器中,而应该引用默认的 ServiceProvider。
所以。如果需要解决某些问题,则会调用默认的 ServiceProvider,如果没有解决方案,则将使用您的自定义 UnityContainer 来解决类型问题。

问题
MVC 总是尝试使用默认的 ServiceProvider 来解析 Controller。
另外,我注意到即使控制器能够正确解析,我也永远无法“混合”依赖项。现在,如果我想使用我的服务之一,但也想使用 ASP 的 IOptions 接口,则该类永远无法解析,因为这两个容器中没有一个具有这两种类型的解析。

我需要的
因此,回顾一下我需要以下内容:

  • 我不需要将 ASP.NET 依赖项复制到 Unity 容器中的设置
  • 一个可以解析我的 MVC 控制器的容器
  • 可以解决“混合”依赖关系的容器

EDIT:
那么问题是我怎样才能实现这些目标呢?

Environment
project.json:
enter image description here


因此,经过一些研究,我针对我的问题提出了以下解决方案:

将 Unity 与 ASP 结合使用
为了能够将 Unity 与 ASP 结合使用,我需要一个自定义 IServiceProvider (ASP 文档 https://docs.asp.net/en/latest/fundamentals/dependency-injection.html#replacing-the-default-services-container)所以我为 IUnityContainer 编写了一个包装器,如下所示

public class UnityServiceProvider : IServiceProvider
{
    private IUnityContainer _container;

    public IUnityContainer UnityContainer => _container;

    public UnityServiceProvider()
    {
        _container = new UnityContainer();
    }

    #region Implementation of IServiceProvider

    /// <summary>Gets the service object of the specified type.</summary>
    /// <returns>A service object of type <paramref name="serviceType" />.-or- null if there is no service object of type <paramref name="serviceType" />.</returns>
    /// <param name="serviceType">An object that specifies the type of service object to get. </param>
    public object GetService(Type serviceType)
    {
        //Delegates the GetService to the Containers Resolve method
        return _container.Resolve(serviceType);
    }

    #endregion
}

此外,我还必须更改 Startup 类中的ConfigureServices 方法的签名:

public void ConfigureServices(IServiceCollection services)

to this:

public IServiceProvider ConfigureServices(IServiceCollection services)

现在我可以返回我的自定义 IServiceProvider,并且将使用它将代替默认的 IServiceProvider。
完整的配置服务方法显示在底部的连接部分。

解析控制器
我发现这篇博文 https://simpleinjector.org/blog/2016/07/working-around-the-asp-net-core-di-abstraction/。从中我了解到 MVC 使用 IControllerActivator 接口来处理控制器实例化。所以我自己写了一个,看起来像这样:

public class UnityControllerActivator : IControllerActivator
{
    private IUnityContainer _unityContainer;

    public UnityControllerActivator(IUnityContainer container)
    {
        _unityContainer = container;
    }

    #region Implementation of IControllerActivator

    public object Create(ControllerContext context)
    {
        return _unityContainer.Resolve(context.ActionDescriptor.ControllerTypeInfo.AsType());
    }


    public void Release(ControllerContext context, object controller)
    {
        //ignored
    }

    #endregion
}

现在,如果激活一个 Controller 类,它将使用我的 UnityContainer 进行实例化。因此我的 Unity 容器必须知道如何解析任何控制器!

下一个问题:使用默认的 IServiceProvider
现在,如果我在 ASP.NET 中注册 Mvc 等服务,我通常会这样做:

services.AddMvc();

现在,如果我使用 UnityContainer,则所有 MVC 依赖项都无法解析,因为它们未注册。所以我可以注册它们(如 AutoFac),也可以创建一个 UnityContainerExtension。我选择了扩展并提出了以下两个类:
UnityFallbackProvider扩展

public class UnityFallbackProviderExtension : UnityContainerExtension
{
    #region Const

    ///Used for Resolving the Default Container inside the UnityFallbackProviderStrategy class
    public const string FALLBACK_PROVIDER_NAME = "UnityFallbackProvider";

    #endregion

    #region Vars

    // The default Service Provider so I can Register it to the IUnityContainer
    private IServiceProvider _defaultServiceProvider;

    #endregion

    #region Constructors

    /// <summary>
    /// Creates a new instance of the UnityFallbackProviderExtension class
    /// </summary>
    /// <param name="defaultServiceProvider">The default Provider used to fall back to</param>
    public UnityFallbackProviderExtension(IServiceProvider defaultServiceProvider)
    {
        _defaultServiceProvider = defaultServiceProvider;
    }

    #endregion

    #region Overrides of UnityContainerExtension

    /// <summary>
    /// Initializes the container with this extension's functionality.
    /// </summary>
    /// <remarks>
    /// When overridden in a derived class, this method will modify the given
    /// <see cref="T:Microsoft.Practices.Unity.ExtensionContext" /> by adding strategies, policies, etc. to
    /// install it's functions into the container.</remarks>
    protected override void Initialize()
    {
        // Register the default IServiceProvider with a name.
        // Now the UnityFallbackProviderStrategy can Resolve the default Provider if needed
        Context.Container.RegisterInstance(FALLBACK_PROVIDER_NAME, _defaultServiceProvider);

        // Create the UnityFallbackProviderStrategy with our UnityContainer
        var strategy = new UnityFallbackProviderStrategy(Context.Container);

        // Adding the UnityFallbackProviderStrategy to be executed with the PreCreation LifeCycleHook
        // PreCreation because if it isnt registerd with the IUnityContainer there will be an Exception
        // Now if the IUnityContainer "magically" gets a Instance of a Type it will accept it and move on
        Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
    }

    #endregion
}


UnityFallbackProvider策略:

public class UnityFallbackProviderStrategy : BuilderStrategy
{
    private IUnityContainer _container;

    public UnityFallbackProviderStrategy(IUnityContainer container)
    {
        _container = container;
    }

    #region Overrides of BuilderStrategy

    /// <summary>
    /// Called during the chain of responsibility for a build operation. The
    /// PreBuildUp method is called when the chain is being executed in the
    /// forward direction.
    /// </summary>
    /// <param name="context">Context of the build operation.</param>
    public override void PreBuildUp(IBuilderContext context)
    {
        NamedTypeBuildKey key = context.OriginalBuildKey;

        // Checking if the Type we are resolving is registered with the Container
        if (!_container.IsRegistered(key.Type))
        {
            // If not we first get our default IServiceProvider and then try to resolve the type with it
            // Then we save the Type in the Existing Property of IBuilderContext to tell Unity
            // that it doesnt need to resolve the Type
            context.Existing = _container.Resolve<IServiceProvider>(UnityFallbackProviderExtension.FALLBACK_PROVIDER_NAME).GetService(key.Type);
        }

        // Otherwise we do the default stuff
        base.PreBuildUp(context);
    }

    #endregion
}

现在,如果我的 UnityContainer 没有注册某些东西,它只需向默认提供者询问即可。
我从几篇不同的文章中了解到了所有这些

  • MSDN Unity 文章 https://msdn.microsoft.com/en-us/library/dn178462(v=pandp.30).aspx
  • 自动模拟 Unity 容器扩展 http://www.mikevalenty.com/auto-mocking-unity-container-extension/
  • 自定义对象工厂 Unity 扩展 http://mark-dot-net.blogspot.de/2009/09/custom-object-factory-unity-extension.html

这种方法的好处是我现在还可以“混合”依赖项。如果我需要任何服务和 ASP 的 IOptions 接口,我的 UnityContainer 将解析所有这些依赖项并将它们注入我的控制器!
唯一要记住的是,如果我使用任何自己的依赖项,我必须向 Unity 注册我的控制器类,因为默认的 IServiceProvider 无法再解析我的控制器依赖项。

最后:连线
现在,在我的项目中,我使用不同的服务(ASP 选项、带选项的 MVC)。为了使这一切正常工作,我的ConfigureServices方法现在看起来像这样:

public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        // Add all the ASP services here
        // #region ASP
        services.AddOptions();
        services.Configure<WcfOptions>(Configuration.GetSection("wcfOptions"));

        var globalAuthFilter = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();

        services.AddMvc(options => { options.Filters.Add(new AuthorizeFilter(globalAuthFilter)); })
                .AddJsonOptions
            (
                options => options.SerializerSettings.ContractResolver = new DefaultContractResolver()
            );
        // #endregion ASP

        // Creating the UnityServiceProvider
        var unityServiceProvider = new UnityServiceProvider();

        IUnityContainer container = unityServiceProvider.UnityContainer;

        // Adding the Controller Activator
        // Caution!!! Do this before you Build the ServiceProvider !!!
        services.AddSingleton<IControllerActivator>(new UnityControllerActivator(container));

        //Now build the Service Provider
        var defaultProvider = services.BuildServiceProvider();

        // Configure UnityContainer
        // #region Unity

        //Add the Fallback extension with the default provider
        container.AddExtension(new UnityFallbackProviderExtension(defaultProvider));

        // Register custom Types here

        container.RegisterType<ITest, Test>();

        container.RegisterType<HomeController>();
        container.RegisterType<AuthController>();

        // #endregion Unity

        return unityServiceProvider;
    }

因为我在过去的一周里学到了关于 DI 的大部分知识,所以我希望我没有打破任何大的原则/模式,如果是的话请告诉我!

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

Unity 与 ASP.NET Core 和 MVC6(核心) 的相关文章

  • 在调用堆栈中看到大量 clr!CLR Semaphore::Wait

    我们看到很多像下面这样的调用堆栈 我可以知道什么条件 情况会发生这种情况吗 OS Thread Id 0x48654 559 Current frame ntdll NtWaitForSingleObject 0xa Child SP Re
  • 在 DataGridView 中隐藏行非常慢

    我在 Winforms 应用程序中有一个 DataGridView 大约有 1000 行 未绑定 和 50 列 隐藏一列需要整整 2 秒 当我想隐藏大约一半的行时 这就成为一个问题 private void ShowRows string
  • 操作/Lambda 表达式内存管理问题

    我将一个操作存储在局部变量中 然后在该局部变量超出范围后使用 使用前是否有被清理的危险 这是一个例子 public List GetMaps Action
  • “包含字符串”的快速索引

    在我的应用程序中 我有多达数百万个短字符串 大部分短于 32 个字符 我想实现一个带有附加列表的搜索框 该列表仅包含包含在搜索框中输入的整个字符串的元素 如何预先建立索引来快速找到此类字符串 所有排序的 STL 容器都会检查整个字符串 对于
  • C++:将模板参数的模板类型成员添加为好友的正确语法?

    我有一个带有模板类型参数 tTRAIT 的类 我想加一个模板为好友type member aliastTRAIT 但我无法弄清楚语法 这可能吗 template
  • 如何使用boost库读取和写入.ini文件[重复]

    这个问题在这里已经有答案了 如何使用boost库读取和写入 或修改 ini文件 With Boost PropertyTree您可以读取并更新树 然后写入文件 请参阅load and save功能 看一下如何访问属性树中的数据 http w
  • asp.net mvc 4 - 可以在每个线程共享 DbContext 吗?

    From 每个 Web 请求一个 DbContext 为什么 https stackoverflow com questions 10585478 one dbcontext per web request why 我的理解是 DbCont
  • 在 C++ 中使用表达式模板进行符号微分

    如何在 C 中使用表达式模板实现符号微分 一般来说 您需要一种表示符号的方法 即编码的表达式模板 例如3 x x 42 以及一个可以计算导数的元函数 希望您对 C 中的元编程足够熟悉 知道这意味着什么和需要什么 但可以给您一个想法 This
  • WinForms - 表单大小错误

    我们有以下代码 private void MainForm Shown object sender EventArgs e RepositionForm private void RepositionForm Rectangle rect
  • 命名空间“Microsoft”中不存在类型或命名空间名称“Practices”

    我正在使用 Microsoft Visual Studio 2005 for c 我的代码中有以下命名空间 using Microsoft Practices EnterpriseLibrary using Microsoft Practi
  • 函数参数评估顺序[重复]

    这个问题在这里已经有答案了 在 C 和 C 中 函数参数的求值是否有固定的顺序 我的意思是 标准怎么说 是吗left to right or right to left 我从书中得到的信息令人困惑 是否有必要function call应该使
  • 如何强制用户仅使用“new”创建从我派生的类的对象?

    为了实现引用计数 我们使用IUnknown http msdn microsoft com en us library ms680509 VS 85 aspx类接口和智能指针模板类 该接口具有所有引用计数方法的实现 包括Release vo
  • 如何填充两个样条线或直线系列之间的区域

    我有这个Chart 如何填充两个之间的区域Series S0 and S1 说蓝色和黄色Series 为此 我们编写了其中之一Paint事件 这里的ValueToPixelPosition https msdn microsoft com
  • ASP.NET MVC 路由 - 向路由添加 .html 扩展名

    我对 MVC 和路由非常陌生 我被要求修改一个应用程序以使用不同的 url 由于我没有经验 这项任务对我来说有点困难 好吧 让我们谈谈一些代码 routes MapRoute CategoryBySeName Route name prod
  • 使用 QGraphicsScene 实现流畅的动画

    我希望我的问题并不总是同样的问题 我有一个 QGraphicsScene 它的项目是一些 QGraphicsPixmap 我用一个计时器来移动它们 每秒 SetX 10 我设置 10是因为窗口大100 使用这个解决方案我的动画不流畅 我想我
  • 数组与映射的性能

    我必须循环一个大数组中的元素子集 其中每个元素都指向另一个元素 问题来自于检测大图中的连接组件 我的算法如下 1 考虑第一个元素 2 将下一个元素视为前一个元素所指向的元素 3 循环直到没有发现新元素 4 考虑1 3中尚未考虑的下一个元素
  • 该组件没有由 uri 标识的资源

    我想创建一个通用数据网格以在我的所有视图 用户控件上使用 这是我的结构 Class Library called Core Class called ViewBase public class ViewBase UserControl pu
  • TreeView:仅在子节点中存在复选框

    我需要一个树视图控件 根节点没有复选框 只有图像 所有子节点都有一个复选框 图像 C net 2 0 winforms 不是 wpf WinForms树视图默认不支持混合复选框 非复选框节点 您可以在树视图上全局启用复选框 并使用以下命令在
  • 非静态类中的静态方法和静态类中的静态方法有什么区别?

    我有两个班级A级和B级 static class ClassA static string SomeMethod return I am a Static Method class ClassB static string SomeMeth
  • 扔掉挥发物安全吗?

    大多数时候 我都是这样做的 class a public a i 100 OK delete int j Compiler happy But is it safe The following code will lead compilat

随机推荐

  • Inno Setup - 更新时删除旧的/过时的文件

    所以 我意识到这个问题以前已经被问过 事实上 在写这篇文章之前 我读了其中的 10 篇文章 但没有一个有适用的解决方案 我希望现在有人已经找到了一些东西 问题 我的程序是使用脚本构建的 在单个文件夹中创建所有最终文件 这些文件包含在 inn
  • 使用 VBA 访问 Outlook 中的文件夹

    我正在使用以下命令将邮件移动到 Outlook 中的文件夹 Dim chemin as String chemin Split path Set myNameSpace Application GetNamespace MAPI Set m
  • 将 Image 数据类型转换为 Base64 并将 Base64 转换为 Image 数据类型

    我在 MS SQL 2012 中使用数据类型 Image 来存储图像 问题 我在 C 中的 BASE64 字符串中有一个图像 9j 4AAQSkZJRgABAQEASABIAAD 4SKhRXhpZgAATU0AKgAAAAgABwESAA
  • 有没有办法让一个对象在 Windows UA 中占据多个网格?

    我正在尝试制作我的第一个应用程序 但我在网格方面遇到了一些问题 我试图将屏幕的左侧设为地图 将右侧设为 2 个框 网格 我不确定是否有办法在多个网格中拥有一个对象 或者如何设置这样的布局 基本上是一个 左线消失了 到目前为止 这是我获得的布
  • 如何创建弹跳div动画

    我正在尝试重新创建弹跳箭头动画 如下所示 http www codecomputerlove com http www codecomputerlove com 但进展并不顺利 我尝试使用 Layerslider 中的内置动画最接近的内容可
  • 带有 标签的 SVG 不可见

    我对 SVG 还比较陌生 我一直在探索各种在线呈现它们的方法 每个似乎都有自己的优点和缺点 但
  • 将文本添加到行尾而不加载文件

    我需要将信息以许多字典的形式存储到一个非常大的文件中 这并不重要 只是说我试图首先将所有数据放入这些字典中 但我耗尽了内存 60Gb 很好 所以我想通过在行上执行循环并向每行附加一些文本来将数据添加到文件中 而不实际将其加载到内存中 那可能
  • Async/Await 是否使用 Task.Run 异步启动新线程?

    我读了很多文章 但仍然无法理解这部分 考虑这段代码 private async void button1 Click object sender EventArgs e await Dosomething private async Tas
  • Matlab中imagesc()的非均匀轴

    问题 是否可以在非均匀轴上说明图像 Details 我需要用图像来说明多维时间序列 但这个时间序列的时间网格非常不均匀 这是一个例子 m 10 n 3 t sort rand m 1 non uniform time values rand
  • :before/:after 伪元素的内容垂直居中

    我正在尝试实现类似于这张图片的效果 我有一个图像 作为幻灯片的一部分 包裹在 div 中 并使用 before 和 after 伪元素 我显示两个控件以移动到幻灯片的下一个 gt gt 或上一个 到目前为止 我有这个 div positio
  • 如何检查 emacs 是在框架中还是在终端中?

    基于这个问题 如何将emacsclient背景设置为Emacs背景 https stackoverflow com questions 9271930 how to set emacsclient background as emacs b
  • PHP内存限制

    在 PHP 5 0 4 中 如果您don t配置 enable memory limit 时 将忽略 memory limit 指令 在推荐的 php ini 文件中它被设置为 8M 但文档说它被忽略 那么在这种情况下 是否存在每个脚本的内
  • 使用客户端指纹对 JWT 令牌进行编码?

    我想知道是否会是最佳实践使用客户端指纹作为 JWT 秘密进行编码 然而 我在 WWW 上找不到有关这个问题的任何内容 但到目前为止 我这样做是有意义的 我正在考虑使用 JavaScript 生成指纹客户端 并在每次调用时将其发送到 API
  • 如何添加tailwindcss到vite?

    我在用着vite https github com vuejs vite 0 16 6并想将 vuepress 站点迁移到使用 vite 但是我不确定如何配置 vite 以使用 tailwindcss in my index css tai
  • 如何让3个textView控件大小相同

    在我的活动中我定义了 3 个 textView 控件 所有这些 textView 都一个挨着一个出现 我需要做一些事情 使它们始终具有相同的大小 假设第一个 textView 控件是小时 第二个 textView 控件是分钟 第三个 tex
  • 多个 Asp.Net 项目之间的共享代码 [重复]

    这个问题在这里已经有答案了 在同一服务器上的多个 Web 应用程序之间共享 bin 文件夹和 dll 以及其他资源文件 如 css 的最佳实践是什么 我已经将通用代码分离到它们自己的程序集中 但我想知道部署等 我基本上希望将所有通用文件位于
  • Meteor 需要时间才能知道是否存在 {{currentUser}}

    我有一些代码 我只想在存在时运行noUser和一些当有currentUser 所有这些都在导航模板内 就像这样 if currentUser li class nav a href Post a li li class nav a Ola
  • 如何在 Chrome 扩展程序中录制音频?

    设置 Chrome 扩展程序以从麦克风录制音频的最简单方法是什么 我看到有一个工作实验性语音输入API http code google com chrome extensions trunk experimental speechInpu
  • 将参数传递给函数以使用 ggplot stat_function 进行绘图

    我有一个函数和一个参数列表 F lt function a b a b b a L lt list a 5 b 2 c 0 我想用未知的 x 或 x 替换参数之一 a b 或 c 并使用 ggplot 的 stat function 进行绘
  • Unity 与 ASP.NET Core 和 MVC6(核心)

    更新 09 08 2018Unity正在开发中here https github com unitycontainer container但我还没有时间测试它如何与 ASP NET Core 框架配合使用 更新 15 03 2018此解决方