Tuesday, February 1, 2011

Customize SPMetal Generated Code for SharePoint to LINQ

A common question that has come up with SharePoint 2010 developers. If they are using the SPMetal tool to generate entities (or class definitions) for objects in SharePoint, can they modify the generated code? The first response someone may say is no; that is not possible. The reason being is when you rerun the SPMetal command and then replace the new generated code overtop your existing code, you will lose your changes.

Well there is a solution and is it extremely simple. I actually got the idea from all the coding experiences I had with building customizations into RIA Services with Silverlight. All the SPMetal tool is doing is generating Proxy code and notice that all of the code is generated as partial classes!!! Now the sky is the limit.

So in the example below, here is a custom content type I created called Anonymous Comment. Below is the generated code and you can see it is a partial class. Now all you need to do is add another partial class to your project called, AnonymousComment and add in custom methods. When you use the AnonymousComment class in some other custom code it will be treated as one class definition.

Another neat thing you can is see there are partial methods for OnLoaded, OnValidate and OnCreated. You can extend those methods if you want and they will be called by the framework. One unfortunate thing you cannot do is modify the behavior of the getter and setter properties, but you can handle that in your custom partial class.

/// <summary>
/// The item that will capture an anonymous comment.
/// </summary>
[Microsoft.SharePoint.Linq.ContentTypeAttribute(Name="Anonymous Comment", Id="0x0100E3A8FCEBECB140D2812D4F3DE177EFEC")]
public partial class AnonymousComment : Item {

private string _comment;

private System.Nullable<System.DateTime> _created;

private string _response;

private System.Nullable<System.DateTime> _responseDate;

private System.Nullable<Category0> _category;

private System.Nullable<Status> _status;

#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate();
partial void OnCreated();
#endregion

public AnonymousComment() {
this.OnCreated();
}

[Microsoft.SharePoint.Linq.ColumnAttribute(Name="AnonymousComment", Storage="_comment", FieldType="Note")]
public string Comment {
get {
return this._comment;
}
set {
if ((value != this._comment)) {
this.OnPropertyChanging("Comment", this._comment);
this._comment = value;
this.OnPropertyChanged("Comment");
}
}
}

[Microsoft.SharePoint.Linq.ColumnAttribute(Name="Created", Storage="_created", ReadOnly=true, FieldType="DateTime")]
public System.Nullable<System.DateTime> Created {
get {
return this._created;
}
set {
if ((value != this._created)) {
this.OnPropertyChanging("Created", this._created);
this._created = value;
this.OnPropertyChanged("Created");
}
}
}

[Microsoft.SharePoint.Linq.ColumnAttribute(Name="AnonymousCommentResponse", Storage="_response", FieldType="Note")]
public string Response {
get {
return this._response;
}
set {
if ((value != this._response)) {
this.OnPropertyChanging("Response", this._response);
this._response = value;
this.OnPropertyChanged("Response");
}
}
}

[Microsoft.SharePoint.Linq.ColumnAttribute(Name="AnonymousCommentResponseDate", Storage="_responseDate", FieldType="DateTime")]
public System.Nullable<System.DateTime> ResponseDate {
get {
return this._responseDate;
}
set {
if ((value != this._responseDate)) {
this.OnPropertyChanging("ResponseDate", this._responseDate);
this._responseDate = value;
this.OnPropertyChanged("ResponseDate");
}
}
}

[Microsoft.SharePoint.Linq.ColumnAttribute(Name="AnonymousCommentCategory", Storage="_category", FieldType="Choice")]
public System.Nullable<Category0> Category {
get {
return this._category;
}
set {
if ((value != this._category)) {
this.OnPropertyChanging("Category", this._category);
this._category = value;
this.OnPropertyChanged("Category");
}
}
}

[Microsoft.SharePoint.Linq.ColumnAttribute(Name="AnonymousCommentStatus", Storage="_status", FieldType="Choice")]
public System.Nullable<Status> Status {
get {
return this._status;
}
set {
if ((value != this._status)) {
this.OnPropertyChanging("Status", this._status);
this._status = value;
this.OnPropertyChanged("Status");
}
}
}
}

No comments: