【发布时间】:2014-12-12 10:26:54
【问题描述】:
我的问题是 Autofac(SimpleInjector 正常工作)我如何创建可以从 MVC 控制器和类库轻松访问的静态类,有很多类似的问题,但我仍然没有得到我正在寻找的答案。
我正在尝试使用 MVC 后面的类库中的 Autofac 解析器,但出现错误“从请求实例的范围中看不到带有匹配 'AutofacWebRequest' 的标记的范围。”
好的,这是故事的开始。我有单例类 EngineContext 来保存我的 diContainer 并且在我尝试使用 EngineContext.DiContainer.GetInstance() 的类库中,它会收到此错误,因为我从单例实例类中调用了解析器。
我进行了研究以解决不同的问题,但没有运气。当我使用 DepedencyResolver.Current.GetService 它说 HttpContext 错误然后我尝试从 global.asax 传递 DependencyResolver.Current 但是在解析我的请求类型时它总是返回 null。
也试过了 builder.RegisterType().InstancePerMatchingLifetimeScope("child") 使用 (var 生命周期 = container.BeginLifetimeScope("child")) { 但同样它说没有带有标签“子”范围等等的范围。
目前这在我的控制器构造函数和静态类调用中起作用。但如果我从内部控制器方法或较低层的类库调用解析器,则它不起作用。下面是我的代码
MVC 启动
[assembly: PreApplicationStartMethod(typeof(ModuleConfig), "Start")]
[assembly: ApplicationShutdownMethod(typeof(ModuleConfig), "Stop")]
namespace NexusCore.Admin
{
public class ModuleConfig
{
public static void Start()
{
EngineConfig();
}
public static void Stop()
{
}
private static void EngineConfig()
{
// Dependancy Injection initialize
EngineContext.Instance.Initialize(new AutofacFactory(
builder =>
{
builder.RegisterControllers(typeof (MvcApplication).Assembly);
// Unit of Work
builder.RegisterType<ContentContext>().As<IContentContext>().InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerRequest();
builder.RegisterType<WebErrorHandlerFactory>().As<IErrorHandlerFactory>().InstancePerLifetimeScope();
},
new AutofacRegisterAdmin(),
container => DependencyResolver.SetResolver(new AutofacDependencyResolver(container))));
}
}
}
引擎上下文
public class EngineContext : IEngine
{
private static IEngine _instance;
public static IEngine Instance
{
get { return _instance ?? (_instance = new EngineContext()); }
}
private IDiContainer _diContainer;
private ICurrentUserProvider _currentUserProvider;
public IDiContainer DiContainer
{
get
{
if (_diContainer == null)
{
var error = ErrorAdapter.ModelState.AddModelError("", "",
logCode: LogCode.CriticalEngineDiContainerNotInitialized);
throw new Exception(error.ErrorMessage);
}
return _diContainer;
}
}
public ICurrentUserProvider CurrentUser
{
get
{
if (_currentUserProvider == null)
{
var error = ErrorAdapter.ModelState.AddModelError("", "",
logCode: LogCode.CriticalEngineCurrentUserProviderNotInitialized);
throw new Exception(error.ErrorMessage);
}
return _currentUserProvider;
}
}
public void Initialize(IDiContainerFactory diContainerFactory)
{
DiContainerInitialize(diContainerFactory);
CurrentUserProviderInitialize();
}
private void DiContainerInitialize(IDiContainerFactory diContainerFactory)
{
_diContainer = diContainerFactory.Create();
}
private void CurrentUserProviderInitialize()
{
_currentUserProvider = _diContainer.GetInstance<ICurrentUserProvider>();
}
}
迪工厂
public class AutofacFactory : IDiContainerFactory
{
private readonly IContainer _container;
public AutofacFactory(Action<ContainerBuilder> preRegister, IDiRegister register, Action<IContainer> resolver)
{
var builder = new ContainerBuilder();
preRegister(builder);
// init register
Register(builder, register);
_container = builder.Build();
resolver(_container);
}
private void Register(ContainerBuilder builder, IDiRegister register)
{
register.SetBuilder(builder);
register.Register();
}
public IDiContainer Create()
{
return new AutofacContainer(_container);
}
}
迪容器
public class AutofacContainer : IDiContainer
{
private readonly IContainer _container;
public AutofacContainer(IContainer container)
{
_container = container;
}
public TService GetInstance<TService>() where TService : class
{
using (var scope = _container.BeginLifetimeScope())
{
return scope.Resolve<TService>(); // change this line many times.
}
}
}
哪里不工作
public class ComponentServices : IComponentServices
{
public IInstallationService InstallationService
{
get { return GetInstance<IInstallationService>(); }
}
public IMembershipService MembershipService
{
get { return GetInstance<IMembershipService>(); }
}
private T GetInstance<T>() where T : class
{
return EngineContext.Instance.DiContainer.GetInstance<T>(); // Not work in class library
}
}
在 Controller 中,如果我直接使用 membshipService 就可以正常工作
[Authorize]
public class AccountController : Controller
{
private readonly Infrasructure.Security.IAuthenticationManager _userManager;
//private readonly IComponentServices _services;
private readonly IMembershipService _memberhsip;
public AccountController(Infrasructure.Security.IAuthenticationManager userManager, IMembershipService membership)
{}
在控制器中,如果我使用 ComponenetServices 然后使用 _services.MembershipServices 它会出错。因为 ComponentServices 尝试调用 EngineContext.DiContainer.GetInstanct() 然后它会返回 No scope with a Tag matching "AutofacWebRequest" 错误。
【问题讨论】:
标签: design-patterns dependency-injection asp.net-mvc-5 autofac