Autofac ASP.NET MVC5:使用来自控制器和类库</t>的Resolve <t>进行混合

时间:2014-12-12 10:26:54

标签: design-patterns dependency-injection asp.net-mvc-5 autofac

我的问题是在Autofac(SimpleInjector正常工作)中如何创建可以从MVC控制器和类库轻松访问的静态类,有很多类似的问题,但我仍然没有得到答案我正在寻求

我正在尝试使用MVC背后的类库中的Autofac解析器并获得错误&#34;没有标记匹配的范围&#39; AutofacWebRequest&#39;从请求实例的范围中可见。 &#34;

好的,这是故事的开始。我有单独的类EngineContext,它包含我的diContainer,在我的类库中我试图使用EngineContext.DiContainer.GetInstance()它会得到这个错误,因为我从singlton实例类调用了resolver。

我做了我的研究,以不同的方式工作,但没有运气。当我使用DepedencyResolver.Current.GetService它说HttpContext错误然后我试图从global.asax传递DependencyResolver.Current但它在解析我的请求类型时总是返回null。

也试过了 。builder.RegisterType()InstancePerMatchingLifetimeScope(&#34;子&#34) 使用(var lifetime = container.BeginLifetimeScope(&#34; child&#34;)){ 但同样的说,没有范围与标签&#34;孩子&#34;范围等等。

目前这项工作在我的Controller构造函数和静态类调用中。但是如果我从内层控制器方法或下层的类库中调用解析器,它就无法工作。以下是我的代码

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))));
        }
    }
}

EngineContext

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);
    }
}

Di 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)
    {}

在Controller中,如果我使用ComponenetServices然后使用_services.MembershipServices,它将收到错误。因为ComponentServices尝试调用EngineContext.DiContainer.GetInstanct(),然后使用Tag匹配&#34; AutofacWebRequest&#34;错误会回来。

1 个答案:

答案 0 :(得分:0)

最后,我发现ComponentService的目的可以通过使用属性注入来简单解决,我已经过度复杂了。

public class ComponentServices : IComponentServices
{

    public IInstallationService InstallationService { get; set; }
    public IMembershipService MembershipService { get; set; }
}

只有1行需要修改,然后依赖性解析器会自动注入它们。

        Builder.RegisterType<ComponentServices>().As<IComponentServices>().InstancePerLifetimeScope().PropertiesAutowired();

我的不好,太混淆了。