Nano Hash - криптовалюты, майнинг, программирование

Как динамически зарегистрировать тип (например, другую реализацию) для контейнера Unity на основе URL-адреса веб-приложения?

В настоящее время я застрял на том, что я считаю простой проблемой архитектуры.

У меня есть контроллер (это просто примеры, так как я не могу поделиться своим реальным кодом, но принцип верен):

public class StackOverflowController : Controller
    {
        private readonly IStackOverflowService stackOverflowService;

        public StackOverflowService (IStackOverflowService stackOverflowService)
        {
            this.stackOverflowService = stackOverflowService;
        }

        // GET: StackOverflow
        public ActionResult Index()
        {

            var foo = stackOverflowService.Get(bar);

            return View(foo);
        }
    }

Я использую загрузчик Unity MVC4 для управления инъекциями:

  public static class Bootstrapper
    {

        public static IUnityContainer Initialise()
        {
            var container = BuildUnityContainer();

            DependencyResolver.SetResolver(new UnityDependencyResolver(container));

            return container;
        }

        private static IUnityContainer BuildUnityContainer()
        {
            var container = new UnityContainer();

            container.RegisterType<IStackOverflowService, StackOverflowService>("DefaultStackOverflowService");


            return container;
        }


    }

Пока все хорошо, уколы работают. Где я застреваю, так это в том, что теперь легко основываясь либо на конфигурации, либо на какой-то переменной, которую я хочу изменить в реализации StackOverflowService.

Так, например, если url = "somethingelse.com", я хочу иметь возможность автоматически вводить CustomStackOverflowService, который наследуется от IStackOverflowService. Но тут я теряюсь. Я пытался использовать именованную регистрацию, но не могу понять, как вручную разрешить правильную службу для реализации на основе некоторых альтернативных критериев.

Если бы кто-нибудь мог помочь, это было бы эпично :)

EDIT: Критерии для изменения реализации в идеале должны быть определены в режиме реального времени, так сказать, на основе фактического URL-адреса, который в настоящее время посещается. Это многофункциональная среда, так что это может быть что-то вроде domain.com/stackoverflow против domain2.com/stackoverflow.. Реализация должна быть разной для каждого сайта. Я даже не знаю, возможно ли это, если честно, и как это сделать. Я довольно новичок во всей теме IoC.

РЕДАКТИРОВАТЬ 2: я немного продвинулся в этом вопросе и смог вручную вызвать конкретную реализацию. Сейчас я рассматриваю возможность использования фабрики пользовательских контроллеров, чтобы решить, какую реализацию использовать, но я не уверен, что это правильный путь или есть более простой способ сделать это.

Мне нужно иметь в виду, что по мере того, как появляется больше клиентов, мне нужно иметь возможность быстро добавлять больше реализаций для каждого нового клиента. Поэтому в идеале у меня был бы простой способ управлять методами для конкретного клиента.

EDIT 3: Дальнейшее обновление: я переписал свой контроллер, чтобы разрешить внедрение конструктора для определения зависимости. Однако моя первоначальная проблема все еще действительна, так как она срабатывает при создании контроллера, у меня нет доступа к запросу и, следовательно, я не могу определить URL-адрес для разрешения зависимости. Любые идеи были бы хорошы.


  • Я делал много подобных вещей, и реализация зависит от сложности, необходимой для приложения, или от того, насколько простой должна быть конфигурация. вы можете поместить его в свой собственный XML или в файл .config. вы можете создать свой собственный атрибут класса и сканировать папки для реализации вашего интерфейса в соответствии со значением в атрибуте. или простой заводской метод с выключателем. 17.10.2014
  • у вас есть базовый пример фабричного метода? 17.10.2014

Ответы:


1

Использование IControllerFactory и дочерних контейнеров должно работать, но тесно связывает ваш преобразователь зависимостей MVC с Unity.

Сначала измените загрузчик, чтобы создать дочерний контейнер для каждого домена, и настройте каждый дочерний контейнер со специальной регистрацией, необходимой для этого домена. Кроме того, нам нужно сообщить MVC, что у нас есть IControllerFactory, который мы хотим использовать.

public class Bootstrapper
{
    public static IUnityContainer Initialize()
    {
        var container = BuildUnityContainer();

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        return container;
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();

        // Register unity controller factory to resolve controllers
        container.RegisterType<IControllerFactory, UnityControllerFactory>();

        // default registrations
        container.RegisterType<IStackOverFlowService, StackOverflowService>();

        // Do special registration per domain
        LocalHostRegistrations(container);
        SomeThingElseRegistrations(container);

        return container;
    }

    private static void LocalHostRegistrations(IUnityContainer container)
    {
        // you can create a child container per domain
        var localHostContainer = container.CreateChildContainer();
        // all special registrations for localhost go in this container
        // any registrations that are the same as the default we can leave off and unity will 
        //  auto find them from the parent
        localHostContainer.RegisterType<IStackOverFlowService, LocalHostStackOverflowService>();

        // register the child container in the parent container with a registration name
        container.RegisterInstance(typeof(IUnityContainer), "localhost", localHostContainer);
    }

    private static void SomeThingElseRegistrations(IUnityContainer container)
    {
        var localHostContainer = container.CreateChildContainer();
        localHostContainer.RegisterType<IStackOverFlowService, CustomStackOverflowService>();
        container.RegisterInstance(typeof(IUnityContainer), "somethingelse", localHostContainer);
    }
}

Теперь мы создаем фабрику контроллеров.

public class UnityControllerFactory : DefaultControllerFactory 
{
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        IController controller = null;
        var type = GetControllerType(requestContext, controllerName);
        if (type != null)
        {
            // read host from incoming url
            var domain = requestContext.HttpContext.Request.Url.Host.ToLower();
            // get parent unity container
            var container = DependencyResolver.Current.GetService<IUnityContainer>();
            // check if there is a child container for this domain
            if (container.IsRegistered<IUnityContainer>(domain))
            {
                container = container.Resolve<IUnityContainer>(domain);
            }

            controller = container.Resolve(type) as IController;
        }

        // if didn't find type or not right type just pass into base to handle errors
        if (controller == null)
        {
           return base.CreateController(requestContext, controllerName);
        }
        return controller;
    }
}

Эта фабрика извлечет родительский контейнер единства из преобразователя зависимостей MVC и проверит, зарегистрированы ли какие-либо дочерние контейнеры. Если это так, он будет использовать дочерний контейнер для разрешения контроллера и внедрения любых регистраций, которые являются специальными для дочернего контейнера. Это тесно связывает контейнер единства с преобразователем зависимостей MVC и обходит преобразователь зависимостей и использует единство напрямую, но должно дать вам то, что вы ищете.

21.10.2014
  • Спасибо, извините, сегодня проверю, но похоже то, что нужно 23.10.2014
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..