Orchard 中的 ContentHandler 问题(循环引用)



crosspost: https://orchard.codeplex.com/discussions/459007

我的第一个问题是,在 2 个

不同的模块中为同一部件配备 2 个部件处理程序会产生什么影响?

陷入了这种困境,因为一旦创建了特定的内容类型,我就必须运行一个方法。为该部件挂接OnCreate一样容易,但是,这是我的方案:

  • 模块 A 包含部件和原始处理程序
  • 模块 B 包含方法所在的服务
  • 模块 B 引用了模块 A

因此,我无法在模块 A(循环引用(中引用模块 B。所以我所做的是在模块 A 中复制完全相同的 PartHandler 并将其放置在模块 B 中。

这有什么问题吗?

然后是我的第二个问题,我认为它可以解决所有这些问题:我们可以为内容项的默认内容部件创建一个部件处理程序吗?(即所有自定义字段都附加到的部分(

这肯定会让事情变得更容易,因为我可以整合需要在那里运行的东西。

更新 1(更好地解释问题 2(

    ContentDefinitionManager.AlterPartDefinition("EventItem",           
      builder => builder                         
                    .WithField("StartDate", cfg => cfg
                        .OfType("DateTimeField")
                        .WithDisplayName("Start Date")
                        .WithSetting("DateTimeFieldSettings.Display", "DateOnly")
                        .WithSetting("DateTimeFieldSettings.Required", "true"))
                    .WithField("StartTime", cfg => cfg
                        .OfType("DateTimeField")
                        .WithDisplayName("Start Time")
                        .WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
                    .WithField("EndDate", cfg => cfg
                        .OfType("DateTimeField")
                        .WithDisplayName("End Date")
                        .WithSetting("DateTimeFieldSettings.Display", "DateOnly"))
                    .WithField("EndTime", cfg => cfg
                        .OfType("DateTimeField")
                        .WithDisplayName("End Time")
                        .WithSetting("DateTimeFieldSettings.Display", "TimeOnly"))
                    .WithField("Intro", cfg => cfg
                        .OfType("TextField")
                        .WithDisplayName("Intro")
                        .WithSetting("TextFieldSettings.Flavor", "textarea"))
    ContentDefinitionManager.AlterTypeDefinition(
        "EventItem"
        , cfg =>
            cfg
                .DisplayedAs("Event Item")                        
                .WithPart("TitlePart")
                .WithPart("EventItem")
                .WithPart("LocationPart")   
                .WithPart("AutoroutePart", builder => builder
                    .WithSetting("AutorouteSettings.AllowCustomPattern", "true")
                    .WithSetting("AutorouteSettings.AutomaticAdjustmentOnEdit", "false")
                    .WithSetting("AutorouteSettings.PatternDefinitions", "[{Name:'Title', Pattern: 'learn/events/{Content.Slug}', Description: 'learn/events/event-title'}]")
                    .WithSetting("AutorouteSettings.DefaultPatternIndex", "0"))
                .WithPart("CommonPart")
                .Draftable()
                .Creatable()
    );

我说的是要为包含所有自定义字段的 EventItem 部分创建一个内容处理程序。当解决方案中的任何类中未定义 EventItemPart 时,我该怎么做?

下面的操作将不起作用,因为它找不到类 EventItemPart:

OnCreated<EventItemPart>((context, keynotes) =>
    questionService.SetDefaultQuestions(context.ContentItem));

交叉回答也是如此。

  1. 伯特兰完全正确。为什么首先需要在 A 中引用 B?如果来自 B 的服务需要 A 并且 A 需要此服务,那么它属于 A(至少是接口 - 合约(。

    您始终可以拆分服务的接口和实际实现,其中一个位于不同的模块中。如果你的服务实现需要来自 B 的东西,那么把接口放在 A 中,但实际实现在 B 中。这样 A 甚至不需要知道 B 的存在,但仍然可以通过它的接口使用服务 - 这是 IoC 模式和 Orchard 模块化的美妙之处:(

  2. 可以使用 ContentPartIContent 作为处理程序泛型方法中的类型参数。这是完全有效的。这样,您就可以插入所有项目的事件,然后执行自定义过滤(基于类型名称、某些字段存在等(。在您的情况下,它可能看起来像:

    OnCreated<ContentPart>((context, part) => 
    {
        if(part.ContentItem.ContentType != "EventItem") return;
        questionService.SetDefaultQuestions(context.ContentItem);
    });
    

更新:无需执行此操作:.WithPart("EventItem") 。这个"假"部分将由框架自动添加。

交叉回答:

  1. 没有然而,重复自己几乎总是错误的,特别是如果这样做是出于不好的原因。为什么服务和部件在两个不同的模块中?为什么 A 需要 B?圆形参考表示紧密耦合。如果紧密耦合是合理的,那么它应该发生在单个模块中。如果不是,那么您需要重新进行设计以将其删除。

  2. 您可以为任何东西创建一个处理程序,但您对方案的解释是模糊和抽象的,以提供任何有用的建议。

最新更新