我会提出,这个提议的解决方案的可维护性不亚于简单地将数据源关联到代码模板,就像您现在拥有的那样。事实上,我什至会说,通过将模板模式和呈现信息推送到数据库,您将失去灵活性,这将使您的应用程序更难维护。
例如,假设您有这些带有属性的数据源(如果我理解正确的话):
Document { Author, DateModified }
Picture { Size, Caption, Image }
Song { Artist, Length, AlbumCover }
然后,您的搜索结果中可能会包含这些数据源中的一个。每个元素都以不同的方式呈现(图片可以使用锚定在左侧的预览图像来呈现,或者歌曲可以显示专辑封面等)
让我们看看您提出的设计下的渲染。您将查询数据库以获取渲染,然后调整您发出的一些 HTML,例如因为您想要文档的绿色背景和图片的蓝色背景。为了争论,假设您意识到您确实需要三种背景颜色用于歌曲,两种用于图片,一种用于文档。现在,除了更改要应用呈现值的参数化模板之外,您正在查看数据库模式更改,该更改被提升和推出。
假设您决定 Document 结果需要一个下拉控件,Picture 需要几个按钮,Songs 需要一个声音播放器控件。现在,每个数据源的每个模板都发生了巨大的变化,所以你回到了你开始的地方,除了现在你有一个数据库层。
这就是设计中断的原因,因为您现在失去了为每个数据源定义不同模板的灵活性。您丢失的另一件事是在源代码管理中对模板进行版本控制。
我会看看如何在发出的视图中重用通用元素/控件,但将模板和数据源之间的映射保留在工厂中,并将模板作为每个数据源的单独文件保存。看看通过 CSS 或类似的配置设置来维护渲染。为了使其更易于维护,考虑将映射导出为简单的 XML 文件。要部署新的数据源,您只需添加一个映射,创建适当的模板和 CSS 文件,然后将它们放到预期的位置。
回复以下评论:
我的意思是一个简单的 switch 语句就足够了:
switch (resultType)
{
case (ResultType.Song):
factory = new SongResultFactory();
template = factory.BuildResult();
break;
// ...
您有逻辑输出给定模板的地方。如果你想要比长的 switch 语句更紧凑的东西,你可以在字典中创建映射,如下所示:
IDictionary<ResultType, ResultFactory> TemplateMap;
mapping = new Dictionary<ResultType, ResultFactory>();
mapping.Add(ResultType.Song, new SongResultFactory());
// ... for all mappings.
然后,您可以使用以下单行语句代替 switch 语句:
template = TemplateMap[resultType].CreateTemplate();
我的主要论点是,在某些时候,您仍然必须维护映射——无论是在数据库中、一个大的 switch 语句中,还是在这个需要初始化的 IDictionary 实例中。
您可以更进一步,将映射存储在一个简单的 XML 文件中,该文件读入:
<TemplateMap>
<Mapping ResultType="Song" ResultFactoryType="SongResultFactory" />
<!-- ... -->
</TemplateMap>
并使用反射等。人。填充 IDictionary。您仍在维护映射,但现在在一个 XML 文件中,这可能更容易部署。