在一个类中使用Unity.BuildUp可以在其他类中打破注入

时间:2011-07-25 09:17:20

标签: c# asp.net-mvc dependency-injection unity-container enterprise-library

我有一个会员资格提供程序,它会导致依赖注入问题。 我想了解为什么会发生

这是基本控制器的某些部分。 (它的工作原理应该如此。)

namespace Our.Web.Controllers
{
    public abstract partial class OurBaseController : VABController
    {
        //--------------------------------------
        //  EVENT DECLARATIONS
        //--------------------------------------

        //--------------------------------------
        //  CLASS CONSTANTS
        //--------------------------------------

        //--------------------------------------
        //  PRIVATE VARIABLES
        //--------------------------------------

        private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

        private UserInfo m_info;

        //--------------------------------------
        //  PROTECTED VARIABLES
        //--------------------------------------

        //--------------------------------------
        //  CONSTRUCTOR & INITIALIZATION
        //--------------------------------------

        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
            base.Initialize(requestContext);

            logger.Debug("Initializing OurBaseController.");

            m_info = UserInfoAccessor.GetCurrent();
        }

        //--------------------------------------
        //  GETTER/SETTERS
        //--------------------------------------

        [Dependency]
        public UserInfoAccessor UserInfoAccessor { get; set; }

        <snip>

    }
}

以下是Global.asax.cs的统一注册的相关部分:

namespace OurWeb
{

    public class MvcApplication : System.Web.HttpApplication, IContainerAccessor
    {
        <snip>

        //--------------------------------------
        //  GETTER/SETTERS
        //--------------------------------------

        IUnityContainer IContainerAccessor.Container
        {
            get { return MvcUnityContainer.Container ; }
        }

        //--------------------------------------
        //  EVENT HANDLERS
        //--------------------------------------

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            RegisterRoutes(RouteTable.Routes);

            ConfigureUnity();

            <snip>
        }

        <snip>

        //--------------------------------------
        //  STATIC METHODS
        //--------------------------------------

        <snip>

        //--------------------------------------
        //  PRIVATE & PROTECTED INSTANCE METHODS
        //--------------------------------------

        private void ConfigureUnity()
        {
            //Create UnityContainer          
            IUnityContainer container = new UnityContainer()
                <snip>
                .RegisterType<UserInfoAccessor>()
                <snip>

            //Set container for Controller Factory
            MvcUnityContainer.Container = container;

            <snip>

            //Set Controller Factory as UnityControllerFactory
            ControllerBuilder.Current.SetControllerFactory(
                                typeof(UnityControllerFactory));
        }

        <snip>
    }
}

现在,当我添加自定义成员资格提供程序时,我无法注入它,因此我在构造函数中使用了BuildUp。

namespace System.Web.Security
{
    public class OurMembershipProvider : SqlMembershipProvider
    {
        //--------------------------------------
        //  EVENT DECLARATIONS
        //--------------------------------------

        //--------------------------------------
        //  CLASS CONSTANTS
        //--------------------------------------

        //--------------------------------------
        //  PRIVATE VARIABLES
        //--------------------------------------

        private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();

        //--------------------------------------
        //  PROTECTED VARIABLES
        //--------------------------------------

        //--------------------------------------
        //  CONSTRUCTOR & INITIALIZATION
        //--------------------------------------

        public OurMembershipProvider()
            : base()
        {
            // Can't inject so we'll ask the container to build the instance.
            IUnityContainer container = GetUnityContainer();
            container.BuildUp(this);
        }

        //--------------------------------------
        //  GETTER/SETTERS
        //--------------------------------------

        [Dependency]
        public UserInfoAccessor UserInfoAccessor { get; set; }

        //--------------------------------------
        //  PUBLIC METHODS
        //--------------------------------------

        public override bool ValidateUser(string username, string password)
        {
            //Sufficient for the question. In reality it contains account mapping validation logic.
            return base.ValidateUser(username, password);
        }

        //--------------------------------------
        //  EVENT HANDLERS
        //--------------------------------------

        //--------------------------------------
        //  STATIC METHODS
        //--------------------------------------

        //--------------------------------------
        //  PRIVATE & PROTECTED INSTANCE METHODS
        //--------------------------------------

        private IUnityContainer GetUnityContainer()
        {
            var context = HttpContext.Current;

            if (context == null)
                throw new Exception("No HttpContext");

            var accessor = context.ApplicationInstance as IContainerAccessor;

            if (accessor == null)
                throw new Exception("The global HttpApplication instance needs to implement " + typeof(IContainerAccessor).FullName);

            if (accessor.Container == null)
                throw new Exception("HttpApplication has no container initialized");

            return accessor.Container;
        }
    }
}

该类驻留在MVC Web项目中,所以我刚刚更改了web.config,如下所示:

<!--<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/>-->
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.OurMembershipProvider" connectionStringName="ApplicationServices" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" passwordStrengthRegularExpression="" applicationName="/"/>  

现在,当我完成此操作时,我在此行的OurBaseController的构造函数中得到一个空引用异常:m_info = UserInfoAccessor.GetCurrent();

当我注册这个自定义成员资格提供程序时,Unity怎么没有注入UserInfoAccessor,但是当我回到标准成员资格提供程序时,它工作正常?
BuildUp是否会干扰注射?

我在调试器或elmah中没有任何其他异常。

第20110726号决议

自定义成员资格对象是在设置UnityContainer时创建的。这使得容器无法使用,初始化期间的异常使得UnityContainer保持uninitializad,这就是容器无法使用的原因。

我从中学到了什么?
使用统一容器作为资源定位器就是一堆垃圾。

为什么我在配置过程中错过了错误?
当我启动该站点时,我的Web浏览器打开了一个新选项卡。我放弃了它并刷新了一个早先的窗口。所以我正在查看已经启动该站点的第二个请求的结果。

1 个答案:

答案 0 :(得分:1)

自定义成员资格对象是在设置UnityContainer时创建的。这使得容器无法使用,初始化期间的异常使得UnityContainer保持uninitializad,这就是容器无法使用的原因。

我从中学到了什么?
使用统一容器作为资源定位器就是一堆垃圾。

为什么我在配置过程中错过了错误?
当我启动该站点时,我的Web浏览器打开了一个新选项卡。我放弃了它并刷新了一个早先的窗口。所以我正在查看已经启动该站点的第二个请求的结果。