The DevForce T4 code generator emits a partial classes. You can add capabilities to the generated entity classes by writing supplemental code in your own partial class files.
You add partial class files to the model project, knowing that the compiler will combine the class definitions it finds in all source code files when it builds the final entity classes.
To illustrate this technique of extending the generated entity classes, we'll add a Customer partial class that enhances the generated Customer class in several ways.
Begin by adding a new source code file to the same model project calling it Customer.cs (or Customer.vb). To this file you could add a Customer class that looks like this one:
C# | [DebuggerDisplay("{ToString()}")] [RequiresAuthentication] public partial class Customer { public Customer() { CustomerID = SystemGuid.NewGuid(); } [Display(Name = "Original", AutoGenerateField = true, Order = 3)] public bool IsOriginal { get { return CustomerID_OLD != String.Empty; } } public bool CanDelete { get { return !IsOriginal; }} // Enforce integrity of order before adding public void AddOrder(Order order) {/*...*/} // Enforce rules for removing an order public void RemoveOrder(Order order) {/*...*/} // Trim spaces from Company name [BeforeSet(EntityPropertyNames.CompanyName)] public void TrimNameBeforeSet( PropertyInterceptorArgs<Customer, String> args) { if (args.Value != null) args.Value = args.Value.Trim(); } public override string ToString() { return String.Format("{0}({1})", CompanyName, CustomerID); } } |
VB | <DebuggerDisplay("{ToString()}")> <RequiresAuthentication> _ Partial Public Class Customer Public Sub New() CustomerID = SystemGuid.NewGuid() End Sub <Display(Name := "Original", AutoGenerateField := True, Order := 3)> Public ReadOnly Property IsOriginal() As Boolean Get Return CustomerID_OLD <> String.Empty End Get End Property Public ReadOnly Property CanDelete() As Boolean Get Return Not IsOriginal End Get End Property ' Enforce integrity of order before adding Public Sub AddOrder(ByVal order As Order) '... End Sub ' Enforce rules for removing an order Public Sub RemoveOrder(ByVal order As Order) '... End Sub ' Trim spaces from Company name <BeforeSet(EntityPropertyNames.CompanyName)> Public Sub TrimNameBeforeSet(ByVal args As PropertyInterceptorArgs(Of Customer, String)) If args.Value IsNot Nothing Then args.Value = args.Value.Trim() End If End Sub Public Overrides Function ToString() As String Return String.Format("{0}({1})", CompanyName, CustomerID) End Function End Class |
The example demonstrates many of the kinds of customizations you might make such as:
Like any .NET class, the compiler imputes a public default, parameterless constructor unless you write a constructor of your own. DevForce doesn't generate a constructor. But you can write one (as shown in the example) and the partial class is a good place to do it.
You might even write a constructor with parameters in which case you must also add a default, parameterless constructor. Another topic covers writing entity constructors in greater detail. For now we'll just call out the importance of having a public default constructor.
We can't use the .NET entity classes in a Silverlight application. The Silverlight application has to have its own version of those classes. To ensure the fidelity of definitions in both .NET and Silverlight environments, the Silverlight model project link to the source code files in the .NET model project.
DevForce takes care of linking to the generated source code files automatically. The developer must link to custom source code files manually.
A partial class can add new features but it cannot change existing features of a generated class. You can't make a public property private. You can't change its implementation either. But you can "re-attribute" them in a metadata "buddy" class.