Orchard CMS:为OpenRasta创建模块,依赖注入问题

时间:2012-02-22 10:26:41

标签: dependency-injection orchardcms openrasta

我正在尝试创建一个Orchard CMS模块,该模块使用OpenRasta为给定路径启用RESTful Web服务(例如/ openrasta / *)。

我需要到Orchard ContentManager获取要返回的服务的内容,因此我的OpenRasta处理程序(ContentHandler)使用ContentService,它实现继承IDependency的IContentService。通常这会起作用,因为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

有没有办法实现这一点,我可以去某个地方的Orchard课并说“给我一个ContentManager实例”吗?

更新:请参阅我对@ rfcdejong关于我的进展更新的回答的评论。

2 个答案:

答案 0 :(得分: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?你可能需要解析界面。

我想你想要以下工作:

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

我直接使用了HostContainer.Resolve并且也遇到了问题。我将在我自己的ServiceHostFactory中描述我正在使用的解决方案

你有自己的OrchardServiceHostFactory派生的ServiceHostFactory吗? 在这种情况下,您可以实现以下代码来帮助您解决实例

    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 :(得分:1)

所以问题是您的CMS使用自己的IoC容器。默认情况下,OpenRasta也会这样做。

这意味着OpenRasta将无法看到Orchard中存在的服务。

对于所有其他IoC容器,答案很简单:您使用IoC适配层,让OpenRasta可以在您想要的任何ioc容器中运行。我们支持团结,结构图,城堡和ninject。也就是说,不支持autofac,因为没有人建立它。

解决此问题的最简洁方法(以及将来可能遇到的任何其他问题)将是为openrasta构建自己的autofac ioc适配层。如果您需要帮助,可以加入openeverything邮件列表,开发人员乐意为您提供帮助。