Orchard CMS: создание модуля для OpenRasta, проблемы с внедрением зависимостей - PullRequest
2 голосов
/ 22 февраля 2012

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

Мне нужно добраться до Orchard ContentManager, чтобы получить содержимое для возврата службой, поэтому мой обработчик OpenRasta (ContentHandler) использует ContentService, который реализует IContentService, который наследует IDependency. Обычно это работает, потому что Orchard внедрит 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, потому что его зависимости не могут быть заполнены Конструктор: Orchard.ContentManagement.IContentManager

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

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

Ответы [ 2 ]

4 голосов
/ 22 февраля 2012

Используете ли вы 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? Возможно, вам придется разрешить интерфейс.

Я думаю, вы хотите, чтобы следующее работало:

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

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

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

    private ILifetimeScope _lifetimeScope = null;
    private ILifetimeScope LifetimeScope
    {
        get
        {
            if (_lifetimeScope == null)
            {
                IHttpContextAccessor accessor = HostContainer.Resolve<IHttpContextAccessor>();
                IRunningShellTable runningShellTable = HostContainer.Resolve<IRunningShellTable>();
                ShellSettings shellSettings = runningShellTable.Match(accessor.Current());
                IOrchardHost orchardHost = HostContainer.Resolve<IOrchardHost>();
                ShellContext shellContext = orchardHost.GetShellContext(shellSettings);
                _lifetimeScope = shellContext.LifetimeScope;
            }
            return _lifetimeScope;
        }
    }

Я также создал 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>();
1 голос
/ 22 февраля 2012

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

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

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

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

...