2012-02-22 2 views
2

Я пытаюсь создать модуль CORC CORS, который позволяет веб-службе RESTful использовать OpenRasta для данного маршрута (например, openrasta/*).Orchard CMS: Создание модуля для OpenRasta, проблемы с инъекцией зависимостей

Мне нужно добраться до ContentManager Orchard, чтобы вернуть контент для службы, поэтому мой обработчик OpenRasta (ContentHandler) использует ContentService, который реализует IContentService, который наследует IDependency. Как правило, это будет работать, потому что сад будет впрыскивать ContentManager в конструктор:

public class ContentService : IContentService { 
    public IContentManager content; 

    public ContentService(IContentManager content) { 
     this.content = content; 
    } 

    public IEnumerable<string> GetContentTypeDefinitionNames() { 
     return content.GetContentTypeDefinitions().Select(d => d.Name); 
    } 
} 

Но когда я запускаю его я получаю сообщение об ошибке, потому что OpenRasta ничего не знаю о зависимости Orchard и это пытается создать ContentService не знает, не Orchard, который является достаточно справедливым:

OpenRasta.DI.DependencyResolutionException: не удалось разрешить Типу ContentService, поскольку его зависимостей не может быть fullfilled Constructor: Orchard.ContentManagement.IContentManager

Есть ли способ достичь этого, могу ли я пойти в класс Orchard и сказать «дайте мне экземпляр ContentManager»?

Обновление: См. Мои комментарии по поводу ответа @ rfcdejong для получения обновлений о моем прогрессе.

ответ

4

Вы используете ServiceRoute, добавленный в класс, реализующий IRouteProvider. Посмотрите на резюме ServiceRoute, в котором говорится: «Включает создание маршрутов службы через HTTP в поддержку сценариев REST».

public class Routes : IRouteProvider 
{ 
    public void GetRoutes(ICollection<RouteDescriptor> routes) 
    { 
     foreach (var routeDescriptor in GetRoutes()) 
      routes.Add(routeDescriptor); 
    } 

    private static ServiceRoute _rastaService = new ServiceRoute(
     "openrasta", 
     new MyServiceHostFactory<IOpenRastaService>(), 
     typeof(IOpenRastaService)); 

    public IEnumerable<RouteDescriptor> GetRoutes() 
    { 
     return new[] 
     { 
      new RouteDescriptor 
      { 
       Priority = -1, 
       Route = _rastaService 
      } 
     }; 
    } 
} 

И хотите решить ContentService? U, возможно, придется разрешить интерфейс.

я предполагаю, и хотите, следующие работы:

var contentService = LifetimeScope.ResolveNew<IContentService>(); 

Я использовал HostContainer.Resolve непосредственно и были проблемы, а также. Я опишу решение, которое я использую на данный момент в своем собственном ServiceHostFactory

У вас есть собственный ServiceHostFactory, полученный из OrchardServiceHostFactory? В этом случае и может реализовать следующий код, чтобы помочь у устраняющих

Я также создал LifetimeScopeExtensions, который имеет следующий код

public static class LifetimeScopeExtensions 
{ 
    public static T ResolveNew<T>(this ILifetimeScope scope) 
    { 
     IWorkContextAccessor workContextAccessor = scope.Resolve<IWorkContextAccessor>(); 
     WorkContext workContext = workContextAccessor.GetContext(); 
     if (workContext == null) 
     { 
      using (IWorkContextScope workContextScope = workContextAccessor.CreateWorkContextScope()) 
      { 
       ILifetimeScope lifetimeScope = workContextScope.Resolve<ILifetimeScope>(); 
       return lifetimeScope.Resolve<T>(); 
      } 
     } 
     else 
     { 
      ILifetimeScope lifetimeScope = workContext.Resolve<ILifetimeScope>(); 
      return lifetimeScope.Resolve<T>(); 
     } 
    } 

    public static object ResolveNew(this ILifetimeScope scope, Type type) 
    { 
     IWorkContextAccessor workContextAccessor = scope.Resolve<IWorkContextAccessor>(); 
     WorkContext workContext = workContextAccessor.GetContext(); 
     if (workContext == null) 
     { 
      using (IWorkContextScope workContextScope = workContextAccessor.CreateWorkContextScope()) 
      { 
       ILifetimeScope lifetimeScope = workContextScope.Resolve<ILifetimeScope>(); 
       return lifetimeScope.Resolve(type); 
      } 
     } 
     else 
     { 
      ILifetimeScope lifetimeScope = workContext.Resolve<ILifetimeScope>(); 
      return lifetimeScope.Resolve(type); 
     } 
    } 
} 


     var settingsService = LifetimeScope.ResolveNew<ITokenServiceSettingsService>(); 
+0

PS: Я не знаю о OpenRasta и что вы делаете с этим. Orchard использует Autofac, и все интерфейсы зависимостей регистрируются автоматически. – rfcdejong

+0

Привет @rfcdejong! Большое спасибо за ответ. То, что у вас есть, похоже, что это сработает, но я немного смущен. У меня нет ServiceHostFactory, и я не уверен, что HostContainer должен быть честным - могу ли я получить HostContainer для текущего экземпляра Orchard или мне нужно его создать? – greg84

+0

Кроме того, я действительно хочу разрешить IContentManager: 'var contentManager = LifetimeScope.ResolveNew ();' - IContentService уже может быть разрешен OpenRasta, поскольку я зарегистрировал зависимость напрямую с ним. Это связь между IContentService и IContentManager, с которыми я борюсь. – greg84

1

Так что вопрос в том, что ваша CMS использует свой собственный контейнер IoC , По умолчанию OpenRasta тоже это делает.

Это означает, что услуги, которые присутствуют в Orchard, не будут видны OpenRasta.

Для всех других контейнеров IoC ответ прост: вы используете слой адаптации IoC, который позволяет OpenRasta жить в любом контейнере ioc, который вы хотите. Мы поддерживаем единство, структурную карту, замок и ninject. Тем не менее, autofac не поддерживается, поскольку никто никогда его не строил.

Самый чистый способ решить эту проблему (и любой другой, с которым вы можете столкнуться в будущем для этих проблем), - это создать собственный уровень адаптации autocac ioc для openrasta. Если вам нужна помощь в этом, вы можете присоединиться к списку рассылки, где разработчики будут рады помочь вам.

+0

Спасибо за вашу помощь. Себ, я мог бы просто сделать это в какой-то момент :) Грег. – greg84

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