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

时间:2013-09-24 22:18:43

标签: handler orchardcms orchardcms-1.6 circular-reference

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

我遇到的第一个问题是在2个不同的模块中为同一个Part提供2个PartHandler会产生什么后果?

我陷入了这种困境,因为一旦创建了特定的内容类型,我就必须运行一个方法。对于该部件,可以很容易地挂钩OnCreated,但是,这是我的场景:

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

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

这会有什么问题吗?

然后是我的第二个问题,我认为可以解决所有这些问题:我们可以为内容项的默认内容部分创建PartHandler吗? (即附加所有自定义字段的部分)

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

更新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部分创建一个ContentHandler,它包含所有自定义字段。如果未在解决方案的任何类中定义EventItemPart,我该怎么办呢?

以下内容无效,因为找不到类EventItemPart:

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

2 个答案:

答案 0 :(得分:1)

跨答案:

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

  2. 您可以为任何事物创建处理程序,但是您对场景的解释是模糊和抽象的方式,以提供任何有用的建议。

答案 1 :(得分:1)

交叉回答。

  1. Bertrand完全正确。为什么你需要首先在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);
    });
    
  3. 更新:无需执行此操作:.WithPart("EventItem")。这个“假”部分将由框架自动添加。