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));
交叉回答也是如此。
-
伯特兰完全正确。为什么首先需要在 A 中引用 B?如果来自 B 的服务需要 A 并且 A 需要此服务,那么它属于 A(至少是接口 - 合约(。
您始终可以拆分服务的接口和实际实现,其中一个位于不同的模块中。如果你的服务实现需要来自 B 的东西,那么把接口放在 A 中,但实际实现在 B 中。这样 A 甚至不需要知道 B 的存在,但仍然可以通过它的接口使用服务 - 这是 IoC 模式和 Orchard 模块化的美妙之处:(
-
可以使用
ContentPart
或IContent
作为处理程序泛型方法中的类型参数。这是完全有效的。这样,您就可以插入所有项目的事件,然后执行自定义过滤(基于类型名称、某些字段存在等(。在您的情况下,它可能看起来像:OnCreated<ContentPart>((context, part) => { if(part.ContentItem.ContentType != "EventItem") return; questionService.SetDefaultQuestions(context.ContentItem); });
更新:无需执行此操作:.WithPart("EventItem")
。这个"假"部分将由框架自动添加。
交叉回答:
-
没有然而,重复自己几乎总是错误的,特别是如果这样做是出于不好的原因。为什么服务和部件在两个不同的模块中?为什么 A 需要 B?圆形参考表示紧密耦合。如果紧密耦合是合理的,那么它应该发生在单个模块中。如果不是,那么您需要重新进行设计以将其删除。
-
您可以为任何东西创建一个处理程序,但您对方案的解释是模糊和抽象的,以提供任何有用的建议。