Использование Unity.BuildUp в одном классе прерывает инъекцию в другом классе

У меня есть поставщик членства, который создает проблему с внедрением зависимостей. Я хотел бы понять, почему это происходит.

Это некоторые части базового контроллера. (Работает как надо.)

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.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 неинициализированным, поэтому контейнер был недоступен.

Чему я научился из этого?
Использование контейнера юнити в качестве локатора ресурсов — это полная куча червей.

Почему я пропустил ошибку во время настройки?
Когда я запустил сайт, в моем веб-браузере открылась новая вкладка. Я отказался от этого и обновил предыдущее окно. Итак, я смотрел на результат второго запроса, в котором сайт уже был запущен.


person Carl R    schedule 25.07.2011    source источник
comment
Правильно ли, что сборка отсутствует в объявлении типа?!?   -  person PVitt    schedule 25.07.2011
comment
Как выглядит стек вызовов?   -  person Rory Primrose    schedule 26.07.2011
comment
Какова цель UserInfoAccessor? Вы уверены, что NRE не вызывается внутри метода GetCurrent()? Unity не может вставлять нулевые значения в отмеченные свойства DependencyAttribute: это вызвало бы исключение   -  person onof    schedule 26.07.2011
comment
@Rory Primrose Я обновил вопрос с разрешением.   -  person Carl R    schedule 26.07.2011
comment
@onof Чтобы получить доступ к базе данных для информации о пользователе. Да, введенное значение никогда не вводилось из-за того, что код нарушил конфигурацию единства.   -  person Carl R    schedule 26.07.2011
comment
@Карл, ты должен указать резолюцию как принятый ответ. И я буду голосовать за то, что вы узнали из этого :)   -  person onof    schedule 26.07.2011


Ответы (1)


Пользовательский объект членства был создан при настройке UnityContainer. Это сделало контейнер недоступным, а исключение во время инициализации сделало UnityContainer неинициализированным, поэтому контейнер был недоступен.

Чему я научился из этого?
Использование контейнера юнити в качестве локатора ресурсов — это полная куча червей.

Почему я пропустил ошибку во время настройки?
Когда я запустил сайт, в моем веб-браузере открылась новая вкладка. Я отказался от этого и обновил предыдущее окно. Итак, я смотрел на результат второго запроса, в котором сайт уже был запущен.

person Carl R    schedule 26.07.2011