通过Unity将对象的属性注入启动变为空

时间:2016-03-11 00:36:00

标签: c# asp.net-mvc dependency-injection inversion-of-control unity-container

注意:我最初将此页面命名为“方法通过Unity将对象注入启动变为空”;对方法注入的所有其他引用应该被理解为 property 注入。

我在Asp.Net MVC5项目中使用unity,我最初是通过Unity.Mvc5 nuget包安装的。由于我已将AspNet Identity内容移入其自己的项目中,因此我很难通过app.GetDataProtectionProvider()为其自定义ApplicationUserManager提供对DataProtectionProvider的访问,这可以通过Startup.ConfigureAuth(IAppBuilder应用程序)中的MVC应用程序获得。 (如果标识内容仍在Web项目中,我会按照trailmax的建议进行此操作:http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration/

我已经定义了一个DataProtectionProviderFactory类,如下所示:

public class DataProtectionProviderFactory : MVC5.Web.Identity.IDataProtectionProviderFactory
{

    private IDataProtectionProvider _dp;
    public void SetProvider(IDataProtectionProvider dp)
    {
        _dp = dp;
    }

    public IDataProtectionProvider GetProvider()
    {
        return _dp;
    }
}

然后设置Startup类以及ApplicationUserManager类,以便通过Unity注入方法。在身份项目中,我有:

public class ApplicationUserManager : UserManager<IdentityUser, Guid>
{

    public IDataProtectionProviderFactory DataProtectionProviderFactory { get; set; }
.
.
}

在Web项目中,我有

public partial class Startup
{
    public IDataProtectionProviderFactory DataProtectionProviderFactory { get; set; }

    public void ConfigureAuth(IAppBuilder app )
    { 
        DataProtectionProviderFactory.SetProvider(app.GetDataProtectionProvider());
    }

}

我的UnityConfig.cs文件(基本上):

public static class UnityConfig
{
    public static void RegisterComponents()
    {
        var container = new UnityContainer();

        container.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager(), new InjectionConstructor("Mvc5"));


        container.RegisterType<IDataProtectionProviderFactory, DataProtectionProviderFactory>();
        container.RegisterType<UserManager<IdentityUser, Guid>, ApplicationUserManager>(new HierarchicalLifetimeManager(),
            new InjectionProperty("DataProtectionProviderFactory"));
        container.RegisterType<Startup>(new HierarchicalLifetimeManager(),
            new InjectionProperty("DataProtectionProviderFactory"));

        container.RegisterType<IUserStore<IdentityUser, Guid>, UserStore>(new HierarchicalLifetimeManager());
        container.RegisterType<CustomSigninManager>(new HierarchicalLifetimeManager());                     


        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
        // Startup.DataProtectionProviderFactory is non-null, after resolving in the following line
        var start = container.Resolve<Startup>();

        container.RegisterType<IAuthenticationManager>(
            new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));      

    }
}

如果我在行上的RegisterComponents()中断:

        var start = container.Resolve<Startup>();

然后我可以看到Startup.DataProtectionProviderFactory非空。

但是,当随后执行Startup.ConfigureAuth(IAppBuilder app)时,它的Startup.DataProtectionProviderFactory为null。

更新

按照mnwsmit的建议进行初始更改后,我在UnityConfig.RegisterComponents()调用中添加了一个“new Startup()”参数,产生以下结果:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        UnityConfig.RegisterComponents(new Startup());
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.Name;      
    }

}

1 个答案:

答案 0 :(得分:1)

调用Startup的{​​{1}}类的实例由OWIN而不是Unity创建。因此,在您的设置中,您最终得到了ConfigureAuth类的两个实例,一个注入了依赖项,另一个没有。没有办法让Unity注入依赖于OWIN(你真正的创业公司)创建的实例。您应该对规则进行一个例外,并使用容器作为服务定位器来获取Startup实例,并确保DataProtectionProviderFactory类获取该实例并使用它。例如,如下所示:

Startup