2017-07-20 52 views
0

我在我的项目中使用Autofac,并且大部分工作正常。前一段时间,我需要得到获取当前用户,被告知要做到这一点的最好办法是创建一个包装类是这样的:Autofac,Users and Logging

public class PrincipalProvider : IPrincipalProvider 
{ 
    public IPrincipal User => HttpContext.Current?.User; 
} 

这已经通过我的应用程序没有任何问题的工作。 我现在有一个新的供应商,看起来像这样:

public class WmsProvider : IWmsProvider 
{ 
    private readonly Lazy<ILogProvider> _logProvider; 
    private readonly Lazy<IMessageProvider> _messageProvider; 

    private readonly CormarConfig _config; 
    private readonly ClaimsIdentity _identity; 

    public WmsProvider(IPrincipalProvider principalProvider, Lazy<ILogProvider> logProvider, Lazy<IMessageProvider> messageProvider) 
    { 
     _messageProvider = messageProvider; 
     _logProvider = logProvider; 

     _identity = (ClaimsIdentity)principalProvider.User.Identity; 
    } 

    /// <summary> 
    /// Sends the order to WMS 
    /// </summary> 
    /// <param name="model">The order model</param> 
    public async Task SendAsync(OrderViewModel model) 
    { 
     var request = WmsFactory.Create(model); 
     await _logProvider.Value.TraceAsync($"This is a test", _identity); 
     await _messageProvider.Value.CreateAsync(request, model.OrderNumber, MessageType.Wms, "ORD", Method.POST, null); 
    } 
} 

(我已经剥离出来为简洁的代码的其余部分)

在这种情况下,用户为null,并抛出一个错误(对象实例未找到)。 但是我有一个类似的构造另一个类:

public OrderProvider(CormarConfig config, IOrderService orderSerivce, IPrincipalProvider principalProvider, Lazy<IAccountProvider> accountProvider, Lazy<ICollectionManagerProvider> collectionManagerProvider, Lazy<IEmailProvider> emailProvider, Lazy<IJournalProvider> journalProvider, Lazy<IOrderLineProvider> orderLineProvider, Lazy<IStockProvider> stockProvider, Lazy<webServices> webService, Lazy<ITroposOrderLineService> troposOrderLineService, Lazy<ITroposOrderService> troposOrderService, Lazy<ITroposUnitOfWork> troposUnitOfWork, Lazy<IWmsProvider> wmsProvider) 
    { 
     //Assign our config 
     _config = config; 

     // Add our services to our class 
     _connectionType = config.ConnectionType; 
     _orderService = orderSerivce; 

     // Add our providers to our class 
     _identity = (ClaimsIdentity)principalProvider.User.Identity; 

     // Add our optional providers 
     _accountProvider = accountProvider; 
     _collectionManagerProvider = collectionManagerProvider; 
     _emailProvider = emailProvider; 
     _journalProvider = journalProvider; 
     _orderLineProvider = orderLineProvider; 
     _stockProvider = stockProvider; 
     _webService = webService; 
     _wmsProvider = wmsProvider; 
     _troposOrderLineService = troposOrderLineService; 
     _troposOrderService = troposOrderService; 
     _troposUnitOfWork = troposUnitOfWork; 
    } 

这工作得很好。 两者都注册了相同的方式在我模块

builder.RegisterType<OrderProvider>().As<IOrderProvider>().InstancePerRequest(); 
builder.RegisterType<WmsProvider>().As<IWmsProvider>().InstancePerRequest(); 

builder.RegisterType<PrincipalProvider>().As<IPrincipalProvider>(); 

有一点要注意,就是WmsProvider注入OrderProvider,所以它不是直接注入到控制器。控制器的构造如下:

public OrdersController(IOrderProvider provider) 
{ 
    _provider = provider; 
} 

这可能是问题所在。在依赖关系中,上下文不可用?如果不是解决方案是什么?有没有一种方法可以从孩子那里得到上下文?

任何帮助,将不胜感激。

+0

'在这种情况下,用户为空并引发错误(未找到对象实例)。哪条线会抛出异常?那个异常的类型是什么? – mjwills

回答

0

我想通了。这是因为我说的,背景是不是在嵌套类可用,所以要解决这个问题我每次请求改变PrincipalProvider的登记实例:

builder.RegisterType<PrincipalProvider>().As<IPrincipalProvider>().InstancePerRequest(); 

我改变了PrincipalProvider看起来像这样:

public class PrincipalProvider : IPrincipalProvider 
{ 

    // Readonly fields 
    private readonly HttpContext _current; 

    /// <summary> 
    /// Default constructor 
    /// </summary> 
    public PrincipalProvider() 
    { 
     _current = HttpContext.Current; 
    } 

    /// <summary> 
    /// Gets the current user 
    /// </summary> 
    public IPrincipal User => _current?.User; 
} 

而这解决了我的问题。