Использование Unity.BuildUp в одном классе прерывает внедрение в другом классе - PullRequest
0 голосов
/ 25 июля 2011

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

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

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

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

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

1 Ответ

1 голос
/ 26 июля 2011

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

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

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

...