0

Я пытаюсь настроить новый сайт Sitecore 7.2, и я хочу интегрировать MVC 5, Glass Mapper и Microsoft Unity в качестве контейнера DI, а Sitecore не хочет играть очень красиво.Sitecore DI с Unity

Мой сценарий заключается в следующем:

  • Есть веб-проект под названием PoC.Quotes.Web - это будет содержать только CSS, HTML и любые другие активы, не контроллеры
  • есть библиотека классов проект под названием PoC .Quotes.Controllers - это только содержит контроллеры
  • есть библиотека классов проект под названием PoC.Quotes.DataLayer - это содержать интерфейс ISitecoreRepository и это конкретная реализация SitecoreRepository

В классе SitecoreRepository есть конструктор, который получает один единственный параметр, Контекст Glass Mapper, а один из моих контроллеров получает один единственный параметр в конструкторе ... ISitecoreRepository.

Sitecore хранилище класса:

public class SitecoreRepository : ISitecoreRepository 
{ 
    ISitecoreContext sitecoreContext = null; 

    public SitecoreRepository(ISitecoreContext context) 
    { 
     this.sitecoreContext = context; 
    } 
} 

контроллер класса:

public class HomeController : Controller 
{ 
    private ISitecoreRepository _repository; 
    public HomeController(ISitecoreRepository repository) 
    { 
     this._repository = repository; 
    } 
} 

Каждый раз, когда я запускаю проект Sitecore выдает ошибку о том, что он не может создать контроллер типа (PoC.Quotes.Controllers .HomeController, PoC.Quotes.Controllers). Я предполагаю, что это показывает полное имя, потому что именно так я настроил его в рендеринге контроллера.

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

System.Web.Mvc.DependencyResolver.Current.GetService<ISitecoreRepository>(); 

Результат нулевой, потому что класс SitecoreRepository только имеющий 1 конструктор с 1 параметром и он не будет экземпляр. Как только я получу этот параметр, не задумываясь, все работает отлично.

Однако для меня этот вид не соответствует цели использования контейнера DI.

Я пробовал смотреть на замок Виндзор, но, хотя в Интернете больше документации, ничего не работает, так как у меня возникают похожие проблемы.

Это немного раздражает, потому что, если я запускаю аналогичный тест в базовом приложении MVC 5 (я сделал это, чтобы быть уверенным, что я не сойду с ума), все работает нормально менее чем за 5 минут.

Любые идеи?

Edit:

В интересный поворот, после того, как несколько хороших часов, проведенных по этому вопросу, я заметил, что на самом деле контейнеры либо Unity или Windsor прекрасно работают с одним ограничением ... большой.

В моей визуализации контроллера я установить свойство контроллера как полное имя контроллера:

PoC.Quotes.Controllers.HomeController, PoC.Quotes.Controllers 

Однако, если я пойду в Sitecore и изменить это свойство только Home, по мановению волшебной палочки все хорошо. Я даже пробовал промежуточную версию использования PoC.Quotes.Controllers.Home, но все равно получить сообщение об ошибке.

Не уверен, что я делаю что-то неправильно, но это немного странно.

Любые идеи, как исправить это?

ответ

0

Провел значительное количество времени на это и удалось придумать решение. Было немного долго писать здесь, поэтому я поставил его на сообщение в блоге http://agooddayforscience.blogspot.co.uk/2015/10/sitecore-multi-tenancy-and-di-containers.html

В принципе, это не проблема с Unity или другим контейнером DI, это было вокруг того, как Sitecore обрабатывает полностью квалифицированные имена. Да, я знаю, что в идеале вы не хотите использовать их, но следовать шаблону MVC, но я объяснил больше в блоге о том, зачем использовать полностью квалифицированные имена.

В качестве объяснения высокого уровня проблема заключается в 2 классах Sitecore ControllerRunner и SitecoreControllerFactory. Оба класса содержат некоторые методы, которые идентифицируют полное имя и используют отражение, чтобы вызвать конструктор без параметров для создания экземпляра нового экземпляра. Исправление, которое я применил, отменяет эти методы, чтобы вызвать фабрику контроллера независимо.

Благодарим за предоставленную помощь.

Andrei

0

Пока я не могу определить, как настроены ваши регистрации, похоже, что вам может быть лучше с фабрикой контроллеров. Например, Windsor, но вы можете легко поменять место в Unity. Чтобы вы не изменяли Global.asax, вы также можете использовать WebActivatorEx для подключения к запуску начальной загрузки.

Bootstrapper

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Site.Website.Cms.WindsorConfig), "RegisterComponents")]` 
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Site.Website.Cms.WindsorConfig), "ReleaseComponents")] 

/// <summary> 
/// Provides a bootstrapping and resolving hook for dependency resolution for MVC, Web API, and service locator. 
/// </summary> 
public static class WindsorConfig 
{ 
    private static Lazy<IWindsorContainer> _container; 

    static WindsorConfig() 
    { 
     _container = new Lazy<IWindsorContainer>(() => BuildContainer()); 
    } 

    public static IWindsorContainer WindsorContainer 
    { 
     get 
     { 
      return _container.Value; 
     } 
    } 

    /// <summary> 
    /// Generates and configures the container when the application is started. 
    /// </summary> 
    public static void RegisterComponents() 
    { 
     ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(WindsorContainer)); 
     GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new WindsorControllerActivator(WindsorContainer)); 
    } 

    /// <summary> 
    /// Disposes of the container when the application is shut down. 
    /// </summary> 
    public static void ReleaseComponents() 
    { 
     WindsorContainer.Dispose(); 
    } 
} 

контроллер завод

/// <summary> 
/// Provides controller dependency resolving for ASP.NET MVC controllers. 
/// </summary> 
public class WindsorControllerFactory : DefaultControllerFactory 
{ 
    private readonly IWindsorContainer _container; 

    public WindsorControllerFactory(IWindsorContainer container) 
    { 
     if (container == null) throw new ArgumentNullException("container"); 
     this._container = container; 
    } 

    public override void ReleaseController(IController controller) 
    { 
     this._container.Release(controller); 
    } 

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType) 
    { 
     if (controllerType == null) 
     { 
      throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path)); 
     } 

     return (IController)this._container.Resolve(controllerType); 
    } 
} 
+0

Привет, Джим, спасибо за ваш ответ. Моя конфигурация единства довольно проста, добавив конфигурацию интерфейса ISitecoreRepository и интерфейс ISitecoreContext (Glass Mapper). Я пробовал ранее Castle Windsor с фабрикой, как показано в вашем примере, но попал в ту же проблему. –

+0

Можете ли вы установить контрольную точку в своем коде загрузки, чтобы проверить, что у вас есть Global.asax или WebActivator, работающий в Sitecore? –

+0

После нескольких хороших часов декомпиляции Sitecore.MVC я пришел к выводу, что проблема заключается в имени, которое я указываю для контроллера в Sitecore. Если я просто использую «Главная» как имя, все идеально. Как только я использую полное имя, Sitecore использует Reflection для создания нового объекта и поиска конструктора без параметров. Я все еще рассматриваю его, поскольку это, по-видимому, является ограничением использования полностью квалифицированного имени, связанного с ASP.NET MVC. Любая помощь или идеи оцениваются –

 Смежные вопросы

  • Нет связанных вопросов^_^