【问题标题】:Dependency injection for non controller classes and calling them非控制器类的依赖注入并调用它们
【发布时间】:2020-12-22 04:23:12
【问题描述】:

我试图围绕依赖注入,来自静态类和实例化类的世界。这是我目前拥有的:

[SomeFilter]
public class AController : Controller
{
    private readonly IOptions<AppSettings> _appSettings;

    public AController(IOptions<AppSettings> appSettings)
{
    _appSettings = appSettings;
}

// GET: /characters/
public IActionResult Index()
{
    //do something
}

SomeFilter 被立即调用,并执行此操作:

public class SomeFilter: ActionFilterAttribute, IActionFilter
{
     public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
       OtherClass.RunMe();
    }
}

OtherClass 如下所示:

public class OtherClass
{
    private readonly IOptions<AppSettings> _appSettings;

    public OtherClass(IOptions<AppSettings> appSettings)
{
    _appSettings = appSettings;
}

public RunMe()
{
    //do something
}

我还在 Startup.cs 中将 OtherClass 注册为 service.Singleton。

我收到一条错误消息:

“非静态字段需要对象引用”

用于OtherClass.RunMe(); 电话。

我假设我可以从代码中的任何位置调用这个类,而不必创建它的新实例?本质上,我如何使用依赖注入从其他类调用方法?

【问题讨论】:

    标签: .net-core dependencies


    【解决方案1】:

    您不能在过滤器上注入构造函数。这都是关于运行时顺序的。当您尝试在构造函数上注入时,您的 IoC 容器目前无法访问。您应该使用属性/设置器注入。

    我更喜欢使用结构映射容器来执行此操作。因为结构映射非常容易应用任何类型注入。例如,当您有这样的过滤器注册表时

     public class ActionFilterRegistry : Registry
        {
            public ActionFilterRegistry(Func<IContainer> containerFactory)
            {
                For<IFilterProvider>().Use(
                    new StructureMapFilterProvider(containerFactory));
    
                Policies.SetAllProperties(x =>
                    x.Matching(p =>
                        p.DeclaringType.CanBeCastTo(typeof(ActionFilterAttribute)) &&
                        p.DeclaringType.Namespace.StartsWith("YourNameSpace") &&
                        !p.PropertyType.IsPrimitive &&
                        p.PropertyType != typeof(string)));
            }
        }
    

    然后你在你的 global.asax(prefer) 或你的启动类之一上注册它。 示例 app_Start 方法。

    DependencyResolver.SetResolver(new StructureMapDependencyResolver(() => Container ?? ObjectFactory.Container));
                ObjectFactory.Container.Configure(cfg =>
                {
                    cfg.AddRegistry(new StandardRegistry());
                    cfg.AddRegistry(new ControllerRegistry());
                    cfg.AddRegistry(new ActionFilterRegistry(() => Container));
                    cfg.AddRegistry(new MvcRegistry());                
                }); 
    

    然后您可以使用任何带有注入的过滤器。但请注意,您不应该像您一样使用构造函数注入。

    【讨论】:

      【解决方案2】:

      我找到了一种使用

      注入过滤器的方法
      [ServiceFilter(typeof(MyFilter))] 
      

      而不仅仅是

      [MyFilter] 
      

      和过滤器的

      (ActionExecutingContext context)
      {
          var controller = context.Controller as Controller.  
          controller.whateverIneed
      }
      

      这现在为我提供了我在过滤器中需要的内容。我还意识到,我无法消除使用new 创建对其他类的引用的需要,因为我的印象是Core 的依赖完全是关于“不再有new”。这涉及到我仍在掌握的 Core 的基础知识。

      我最终做的是创建新的类来做一些工作,但它们被设置为服务并在 startup.cs 中注册。我仍在努力研究如何混合注册服务(我可以注入)和工作类的新实例(通常保存静态信息),并在它们之间传递信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-27
        • 1970-01-01
        • 2016-09-08
        • 2016-02-01
        • 1970-01-01
        相关资源
        最近更新 更多