【问题标题】:How to get an instance from the DI system? [duplicate]如何从 DI 系统中获取实例? [复制]
【发布时间】:2015-11-27 13:45:40
【问题描述】:

我正在尝试在 vNext 中重新创建 HttpContext.Current,但我遇到了问题。

到目前为止的代码:

public class CurrentContext 
    {
        public IHttpContextAccessor ctx { get; private set; }

        public CurrentContext(IHttpContextAccessor accessor)
        {
            ctx = accessor;
        }
    }

services.AddTransient<CurrentContext>();

我想使用:

public static class UserFactory
{
    public static void SetCurrentUser(User u)
    {
        //tryed to get the context but GetService returns null
        IHttpContextAccessor _context = ((CurrentContext)CallContextServiceLocator.Locator.ServiceProvider.GetService(serviceType: typeof(CurrentContext))).ctx;
        //add the user to the Session
    }
}

我现在如何在项目中的任何位置获取CurrentContext 的实例?

【问题讨论】:

    标签: c# dependency-injection asp.net-core asp.net-core-mvc


    【解决方案1】:

    我不使用 vNext DI 系统,但我认为您应该为 CurrentContext 定义一个接口,例如

    public interface IContextProvider {
         IHttpContextAccessor GetContext();
    }
    

    然后使用

    public class CurrentContextProvider : IContextProvider
    {
        private readonly IHttpContextAccessor _context;
    
        public CurrentContextProvider(IHttpContextAccessor accessor)
        {
            _context = accessor;
        }
    
        public IHttpContextAccessor GetContext() {
            return _context;
        }
    }
    

    和电线

    services.AddScoped<IContextProvider, CurrentContextProvider>();
    

    但如果你打算只使用上下文,为什么不直接依赖 IHttpContextAccessor - 你需要它的地方?

    【讨论】:

    • 你说在我需要的地方使用它但是我如何实例化IHttpContextAccessor ?我在问如何获得注册服务的实例?
    • 您在哪里需要实例?您应该依赖于您需要的类的构造函数中的IHttpContextAccessor(或我的示例中的IContextProvider)。控制器、自定义类等等。
    • 我需要在静态上下文中向/从用户会话添加/检索数据,例如用户名或用户 ID(来自数据库)
    • 请使用该代码示例更新您的问题 - 这样我就可以看到您要做什么。 :-)
    • vNext DI 仅支持构造函数注入。服务定位器模式是一个不好的做法。
    【解决方案2】:

    你应该在依赖类的构造函数中声明CurrentContext类型的变量:

    public class SomeClassThatUsesCurrentContext
    {
        private readonly SomeClassThatUsesCurrentContext currentContext;
    
        public SomeClassThatUsesCurrentContext(CurrentContext currentContext)
        {
            if (currentContext == null)
                throw new ArgumentNullException("currentContext");
    
            this.currentContext = currentContext;
        }
    }
    

    这些类可能出现在其他类的构造函数中。最后,您通常从 DI 容器中解析高级类的单个实例。你做的地方叫composite root

    而且,正如@janhartmann 所说,通常您应该使用接口或抽象类而不是具体类。

    【讨论】:

    • 我在不同的地方仍然有同样的问题:我现在如何创建SomeClassThatUsesCurrentContext的实例?
    • 通常在 ASP.NET MVC 应用程序中你应该实现你的控制器工厂。详情:blogs.msdn.com/b/webdev/archive/2014/06/17/…
    • 我需要控制器之外的上下文。我已经在控制器中了。
    • 首先,创建UserFactory 可实例化(非静态)类。获取所有必需的类作为构造函数中的参数。要制作一个类的单个实例,请使用 DI 库的生命周期(生活方式、范围)功能。不要使用 service locator 因为它是反模式。如果您需要在某个不是复合根的地方解析某些类,请重新设计您的解决方案。
    猜你喜欢
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多