当前位置: 首页 > 知识库问答 >
问题:

与控制器类以外的类的依赖项注入

璩无尘
2023-03-14

此时,我正在轻松地将东西注入控制器,在某些情况下构建自己的ResolversServices类。生活是美好的。

我不知道如何让框架自动注入到非控制器类中。工作原理是让框架自动注入我的控制器IOptions,这实际上是我项目的配置:

public class MessageCenterController : Controller
{
    private readonly MyOptions _options;

    public MessageCenterController(IOptions<MyOptions> options)
    {
        _options = options.Value;
    }
}

我在想我是否能为自己的课程做同样的事情。当我模仿控制器时,我假设我很接近,就像这样:

public class MyHelper
{
    private readonly ProfileOptions _options;

    public MyHelper(IOptions<ProfileOptions> options)
    {
        _options = options.Value;
    }

    public bool CheckIt()
    {
        return _options.SomeBoolValue;
    }
}

我想我失败的地方是当我这样叫它的时候:

public void DoSomething()
{
    var helper = new MyHelper(??????);

    if (helper.CheckIt())
    {
        // Do Something
    }
}

我跟踪这个的问题实际上是所有关于DI的内容都是在控制器级别上讨论的。我试图寻找它发生在Controller对象源代码中的位置,但它在那里变得有点疯狂。

我知道我可以手动创建一个IOptions实例,并将其传递给MyHelper构造函数,但似乎我应该能够让框架做到这一点,因为它适用于控制器

共有3个答案

莫兴言
2023-03-14

可惜没有直接的办法。我设法使它工作的唯一方法是创建一个静态类,并在其他任何地方使用它,如下所示:

public static class SiteUtils
{

 public static string AppName { get; set; }

    public static string strConnection { get; set; }

}

然后在你的创业课程中,填写如下:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    //normal as detauls , removed for space 
    // set my variables all over the site

    SiteUtils.strConnection = Configuration.GetConnectionString("DefaultConnection");
    SiteUtils.AppName = Configuration.GetValue<string>("AppName");
}

虽然这是一种糟糕的模式,因为这将在应用程序的整个生命周期中保持,我找不到更好的方式在控制器之外使用它。

曾嘉荣
2023-03-14

假设MyHelperMyService使用,然后由控制器使用。

解决这种情况的方法是:

>

services.AddTransient<MyService>();
services.AddTransient<MyHelper>();

控制器在其构造函数中接收MyService的实例。

public HomeController(MyService service) { ... }

MyService构造函数将依次接收MyHelper的实例。

public MyService(MyHelper helper) { ... }

DI框架将能够毫无问题地解决整个对象图。如果您担心每次解析对象时都会创建新实例,您可以阅读不同的生存期和注册选项,如单例生存期或请求生存期。

当您认为必须手动创建某个服务的实例时,您应该非常怀疑,因为您可能最终会进入服务定位器反模式。最好把创建对象留给DI容器。如果您真的发现自己处于这种情况(假设您创建了一个抽象工厂),那么您可以直接使用IServiceProvider(要么在构造函数中请求IServiceProvider,要么使用http pContext中公开的那个)。

var foo = serviceProvider.GetRequiredService<MyHelper>();

我建议阅读关于ASP. Net 5 DI框架和一般依赖注入的具体留档。

徐欣德
2023-03-14

下面是一个在没有任何涉及MVC控制器的情况下使用DI的工作示例。这是我需要做的来理解这个过程,所以也许它会帮助别人。

ShoppingCart对象通过DI获得INotifier的一个实例(该实例通知客户他们的订单)

using Microsoft.Extensions.DependencyInjection;
using System;

namespace DiSample
{
    // STEP 1: Define an interface.
    /// <summary>
    /// Defines how a user is notified. 
    /// </summary>
    public interface INotifier
    {
        void Send(string from, string to, string subject, string body);
    }

    // STEP 2: Implement the interface
    /// <summary>
    /// Implementation of INotifier that notifies users by email.
    /// </summary>
    public class EmailNotifier : INotifier
    {
        public void Send(string from, string to, string subject, string body)
        {
            // TODO: Connect to something that will send an email.
        }
    }

    // STEP 3: Create a class that requires an implementation of the interface.
    public class ShoppingCart
    {
        INotifier _notifier;

        public ShoppingCart(INotifier notifier)
        {
            _notifier = notifier;
        }

        public void PlaceOrder(string customerEmail, string orderInfo)
        {
            _notifier.Send("admin@store.com", customerEmail, $"Order Placed", $"Thank you for your order of {orderInfo}");
        }

    }

    public class Program
    {
        // STEP 4: Create console app to setup DI
        static void Main(string[] args)
        {
            // create service collection
            var serviceCollection = new ServiceCollection();

            // ConfigureServices(serviceCollection)
            serviceCollection.AddTransient<INotifier, EmailNotifier>();

            // create service provider
            var serviceProvider = serviceCollection.BuildServiceProvider();

            // This is where DI magic happens:
            var myCart = ActivatorUtilities.CreateInstance<ShoppingCart>(serviceProvider);

            myCart.PlaceOrder("customer@home.com", "2 Widgets");

            System.Console.Write("Press any key to end.");
            System.Console.ReadLine();
        }
    }
}
 类似资料:
  • 有没有可能使控制器依赖于他们的服务,而不是通过使用服务容器,而是通过纯粹的构造函数依赖注入? 我希望以这种方式编写控制器: 不幸的是,正如我所看到的,Symfony ControllerResolver不通过ServiceContainer而是通过简单的调用创建新的控制器实例。

  • 我有一个这样定义的单例实例: 现在,由于一些变化,这个类必须依赖于几个(3)依赖项。因此,这些依赖项必须在这里注入。 我们如何为这样设计的Singleton类实现依赖注入? 问题是,已经有很多调用方,因此无法使 getInstance 方法来接受依赖关系。 页(page的缩写)我知道使用单例并不总是一种更干净的方式:)(这是现有的代码,我不得不忍受它:) 附注:我正在使用Guice进行依赖注入。

  • 我有一个名为.jar的罐子,它依赖于我的外部库。 执行会得到以下输出, 我尝试用两种方式运行jar 并为DependedClass获得了NoClassDefFoundError 按如下所示更改清单条目后 清单-版本:1.0 创建-由:1.6.0_05(Sun Microsystems Inc.) 主-类:com.os.hw.helloworld 类-路径:c://users/vinay/deskt

  • 像这样的事情让我头疼,这太疯狂了。但事实是: 对于非控制器类,如何使用net core的内置依赖项注入?请提供一个包含实例化的示例。 谢谢

  • 英文原文:http://emberjs.com/guides/controllers/dependencies-between-controllers/ 有时候,特别是在嵌套资源时,可能需要为两个控制器建立某种联系。以下面的路由为例: 1 2 3 4 5 App.Router.map(function() { this.resource("post", { path: "/posts/:po

  • 本文向大家介绍asp.net-core 检索控制器上的依赖项,包括了asp.net-core 检索控制器上的依赖项的使用技巧和注意事项,需要的朋友参考一下 示例 注册后,可以通过在Controller构造函数上添加参数来检索依赖关系。