65.9K
CodeProject 正在变化。 阅读更多。
Home

如何使用 T4 模板引擎为 SharePoint 2010 实现通用实体列表存储库和业务逻辑

starIconstarIconstarIconstarIconstarIcon

5.00/5 (7投票s)

2010 年 8 月 8 日

CPOL

8分钟阅读

viewsIcon

43953

downloadIcon

335

本文介绍如何使用 T4 模板引擎(文本模板转换工具包)为 SharePoint 2010 实现一个通用的、可扩展的实体列表存储库和业务逻辑。

引言

SharePoint API 为开发人员提供了访问各种信息的强大功能,特别是存储在 SharePoint 列表中的数据。但在实际场景和复杂的 SharePoint 项目中,您通常需要一种更有效的方式来访问列表数据。因此,我开发了一个解决方案,它实现了一个通用的实体列表存储库,该存储库将部分使用 T4 模板引擎(也称为 Microsoft 的文本模板转换工具包)创建。此模板引擎是 Visual Studio 2008 和 2010 的一部分。有关 T4 工具包的更多信息,请参阅 此链接

实体列表存储库基于内容类型,为 SharePoint 列表提供类型安全且可扩展的业务逻辑层(BAL)和数据访问层(DAL)。每个列表存储库都与特定的 SharePoint 内容类型相关联,但多个列表存储库可以指向同一个列表。对于关联的内容类型,T4 模板文件将自动生成一个实体类,该类将用于列表存储库。

我们将使用 Visual Studio 2010 Tools for SharePoint Development 和 C# 创建的 SharePoint 解决方案包含三个项目。存储库项目包含实体和存储库代码,一个 T4 模板帮助器项目包含支持和简化模板生成过程的代码,以及 SharePoint 项目本身,它将使用该存储库。

SharePoint 解决方案创建一个名为 Mail Template 的新内容类型和一个名为 Mail Templates 的列表,该列表与该内容类型相关联。邮件模板本身包含类型名称、主题、正文和密送信息。以下代码片段展示了如何使用该存储库的示例。

MailTemplateRepository mr = new MailTemplateRepository();
MailTemplate mt = mr.GetByType("INVITATION");    

GetByType 方法是一个存储库方法,它通过执行 CAML 查询来查询 SharePoint 列表。查询结果会自动转换为 MailTemplate 实体并返回给调用者。

对于每个存储库,开发人员都可以定义一个执行范围。该范围允许定义实体更新或删除是使用 SPList 类的 SystemUpdate 方法还是 Update 方法执行,或者任务是否以特权方式执行。还有其他设置选项可用。以下示例定义了一个实体存储库范围,它使用 SystemUpdate 方法,不触发任何列表项事件,并以特权方式(使用 RunWithElevatedPrivileges)执行更新。

MailTemplateRepository mr = new MailTemplateRepository();
mr.Scope = new EntityRepositoryScope(true); 

MailTemplate mt = mr.GetByType("INVITATION"); 
mt.Subject = "...";
mt.Body = "...";  

mr.Update(mt); 

在许多开发人员必须更新或删除实体而无需自行编程特殊逻辑的情况下,范围设置非常有用。它有助于统一此过程。

存储库项目

存储库项目中基本上有三个主要类:EntityEntityRepositoryEntityRepositoryScopeEntityEntityRepository 类用于创建特定的实体和存储库类,例如 MailTemplateMailTemplateRepository 类。EntityRepositoryScope 类用于控制 SharePoint 列表项的更新和删除过程(见上文)。

存储库项目包含一些帮助器类和自动生成的类。这些文件都组织在项目内的特殊文件夹中。

文件夹 Attributes

此文件夹包含一个名为 FieldIDAttribute 的类,该类在内部由 EntityRepository 类用于读取每个 public 实体属性的字段 ID。存储库类使用字段 ID 来访问字段对象。ID 是一个 GUID 值,用于定义 SharePoint 列表项内的字段。模板 MailTemplate.tt 会自动将 FieldID 属性添加到生成的实体类代码中。

要使用系统实体(如内容类型 Item),必须手动创建实体类,并将 FieldID 属性添加到每个 public 属性(请参阅代码中的 Item.cs 文件)。除了使用内置字段的 GUID 之外,还可以使用特殊符号:[FieldID("[Title]")] 用于 Title 字段。

文件夹 Constants

Constants 文件夹包含具有列表(Lists 类)和枚举(Enums 类)常量的类。此外,子文件夹 Generated 中的模板文件 ContentTypes.tt 会生成一个 ContentTypes 类,该类包含一个部分子类,其中包含模板文件中定义的每个内容类型的 ID 和名称属性。模板文件本身的 fileNames 变量定义了将生成代码的内容类型。FieldIDs.tt 模板与 ContentTypes.tt 模板文件类似,会生成一个包含所有字段 ID 的类。

文件夹 Contracts

所有存储库接口都定义在此文件夹中。通用的 IEntityRepository 接口是主要接口,它定义了存储库的所有基本方法。每个自定义存储库合同都必须继承自此接口,例如 MailTemplateRepository 类实现的 IMailTemplateRepository 接口。

文件夹 Entities

Entities 文件夹包含所有自动生成和手动创建的实体类。基于模板的实体类都定义为部分类,并存储在子文件夹 Generated 中,因此可以扩展它们以添加属性、方法(覆盖)和基类。T4 模板(在子文件夹 Generated 中)生成的 MailTemplate 类将如下所示:

[CompilerGenerated]
public partial class MailTemplate
{ 
  [FieldID("{B0D7F541-0F86-4794-88AE-9CEEA9BC6F02}")] public string Type { get; set; }
  [FieldID("{31C4A2D3-2928-47D3-A534-9C92993538D7}")] public string Body { get; set; }
  [FieldID("{D41A10DE-5A90-4904-8758-1C6EC9EB54EB}")] public string BCC { get; set; }

  protected override string AssociatedList
    { get { return Lists.MailTemplates; } }
  protected override SPContentTypeId AssociatedContentTypeID
    { get { return ContentTypes.MailTemplate.ID; } }
} 

此类将通过 Entities 文件夹中的 MailTemplate.cs 文件的部分代码进行扩展。

[Serializable]
public partial class MailTemplate : Item
{ 
  public override bool Validate()
  {
     // TODO: Implement specific object validations!
     return base.Validate();
  }

  public void SetPlaceholders(Dictionary<string, string> placeholderValues)
  {
     // TODO: Replace placeholders in subject and body texts if available!
  }
} 

为了支持对象序列化,将向类添加 Serializable 属性。MailTemplate 类和内容类型都继承自 SharePoint 中的 Item 实体类和内容类型。为了反映继承关系,基类将是 Item 类。Item 类的定义如下:

[Serializable]
public partial class Item : Entity
{ 
  [FieldID("[Title]")]
  public string Title { get; set; }
} 

由于 Item 类的基类是 Entity 类,因此可以覆盖一些方法(覆盖)。这些可覆盖的方法是 ValidatePrepareBeforeUpdate 等。MailTemplate 类通过覆盖 Validate 方法来实现对象验证,例如检查给定的 BCC 电子邮件地址是否有效或是否存在于系统中。PrepareBeforeUpdate 方法可用于在执行列表项更新之前更改值。

例如,SetPlaceholders 方法可用于替换邮件模板记录的主题和/或正文中的占位符。该方法尚未实现。它仅展示了开发人员在此类存储库系统中使用时的许多选项。

文件夹 Helpers

Helpers 文件夹包含存储库使用的实用程序类。

文件夹 Repositories

Repositories 文件夹包含所有自定义存储库类,例如 MailTemplateRepository。要创建一个新类,请使用 EntityRepository 类作为基类。对于 MailTemplateRepository,基类是 EntityRepository<MailTemplate>EntityRepository 类实现了 IEntityRepository 接口,而自定义的 MailTemplateRepository 类实现了 IMailTemplateRepository 接口。

特定存储库类应至少实现一个构造函数,该构造函数调用基类构造函数,并传入 SharePoint 列表名称和关联的内容类型 ID 进行初始化。MailTemplateRepository 类的 GetByType 方法的实现展示了一个创建 CAML 查询并通过调用基类方法 Get 来执行它的示例。

public IList<MailTemplate> GetByType(string type)
{ 
  if(string.IsNullOrEmpty(type))
    throw new ArgumentNullException("type");

   return Get(
     string.Format("<Eq><FieldRef ID='{0}'/><Value Type='String'>{1}</Value></Eq>",
     FieldIDs.MailTemplate.Type, type));
} 

Get 方法将 CAML 语句转换为最终查询,执行查询,实体化从 SharePoint 收到的列表项,并返回一个实体列表。执行过程使用默认或指定的执行范围。另一种选择是使用方法,这些方法执行 CAML 查询并返回同一存储库类中的实体列表,例如 GetByType 方法作为 LINQ to Objects 的输入,以便进行排序、更改或转换列表。

本文只能为您提供存储库逻辑的概述。要了解如何有效使用该系统并创建新的存储库类,最好的方法是查看源代码并自己进行测试。SharePoint 项目包含一个应用程序页面(Test.aspx),它将使用 MailTemplateRepository 存储库类来显示列表数据。

protected void Page_Load(object sender, EventArgs e)
{ 
   _templateRepository = new MailTemplateRepository();

   if(IsPostBack)
     return;

   var types = _templateRepository.GetTypes();

   if(types == null || types.Count == 0)
     WriteMessage("No mail templates found.");
   else
   {
     MailTemplateTypeList.DataSource = types;
     MailTemplateTypeList.DataBind();
     SetTemplateData(types[0]);
   }
}

...

protected void SetTemplateData(string type)
{ 
   MailTemplate mt = _templateRepository.GetByType(type).FirstOrDefault();

   if(mt == null)
     WriteMessage(string.Format("No mail templates of type '{0}' found.", type));
   else
   {
     SubjectLabel.Text = mt.Title ?? string.Empty;
     BodyLabel.Text = HttpUtility.HtmlEncode(mt.Body ?? string.Empty);
     BccLabel.Text = mt.BCC ?? string.Empty;
   
     Views.SetActiveView(DefaultView);
   }
} 

下一节将简要介绍 T4 模板帮助器项目的工作原理。

T4 模板项目

此项目仅用于简化模板生成过程。它不是生产输出的一部分,也不能部署到 SharePoint 系统。创建一个自定义类库并在模板处理期间调用它是开发人员实现可重用模板帮助器方法的唯一方法。在模板文件中,将引用该类库(仅在 Visual Studio 2010 中)。

<#@ assembly name="$(SolutionDir)MailTemplate.T4\bin\MailTemplate.T4.dll" #> 

本文或项目中使用的所有模板首先会检查哪个 Visual Studio 项目包含项目项(内容类型定义)。内容类型定义的​​文件名在模板文件中的 fileNames 变量中定义。帮助器方法将打开文件并分析 XML/CAML 定义,以了解定义的字段类型和 ID。该信息将返回给模板代码以生成最终的源代码。

模板文件生成的类将使用 CompilerGenerated 属性进行装饰。您可以随意修改模板并根据您的具体需求调整模板代码。也可以调试模板代码,但这超出了本文的范围。Microsoft 的 T4 模板引擎或文本模板转换工具包是实现某些任务自动化的绝佳选择。

摘要

本文概述了 SharePoint 开发领域的几个有趣主题。存储库系统帮助我更有效地开发大型 SharePoint 项目。T4 模板引擎帮助自动化了繁琐的任务,并通过避免忘记调整实体类来减少了错误。该系统的强大功能将体现在您需要处理的实体数量上。

历史

  • 2010 年 8 月 8 日:初始帖子
© . All rights reserved.