How to Derive a New Orders Class
To add custom properties or methods to a core Orders class, you can create a derived class and add the new properties or methods to the derived class. You then update the configuration files for Commerce Server Core Systems to indicate that your derived class replaces the core Orders class. By doing this, you make the Orders pipelines and mapped storage use your new class instead of the core Orders class that it replaces. Because your new class derives from a core Orders class, properties and methods of the other core Orders classes that used the base class will work unchanged with your new class. For example, if you derive the class MyLineItem from the core LineItem class, the LineItemCollection class will contain LineItem objects, which you can cast into MyLineItem objects. For more information about the configuration files to update, see How to Integrate a Derived Class with the Orders System.
This topic includes the code for a complete example that extends the LineItem class, and provides a procedure for creating each part of the code. For this example, assume that your Web site sells widgets with a description printed on the widget. For each widget that a customer orders, you need to know what to print. You will replace Commerce Server Core Systems’s LineItem class with your own class, and add a new property to your class to store the description to print.
Note
Do not give your derived class the same name as one of the core Orders classes, even if your derived class is in a different namespace.
Note
Do not derive a new class directly from the OrderGroup class. Instead, derive the class from a class that inherits from OrderGroup: Basket, OrderTemplate, or PurchaseOrder.
Warning
Extending LineItems still allows the LineItems in old orders to be retrieved, but LineItems in old baskets will fail to load. This is because the basket LineItems are saved as a BLOB and extending LineItems does not automatically update older basket BLOBs.
The following procedure illustrates how to extend the LineItem class to include an additional property. Each step of the procedure includes the code to implement that step, and the entire sample is included at the end of this topic. Although the sample code implements the example of printing a description on widgets, you can use the same structure to add your own properties.
To extend an Orders class
In Visual Studio, create a new Commerce Server Core Systems project.
Add using directives for the necessary namespaces, including Microsoft.CommerceServer.Runtime.Orders.
using System; using System.Runtime.Serialization; using System.Security.Permissions; using Microsoft.CommerceServer.Runtime.Orders;
Create a namespace. For this example, call the namespace MyOrdersClasses.
namespace MyOrdersClasses { }
Create a new class that derives from the base Orders class and adds the Serializable attribute to the class. For this example, create the class MyLineItem and derive it from the LineItem class.
[Serializable] public class MyLineItem : LineItem { }
Add a private member variable to the derived class to store the new information. For this example, add a string variable named widgetDescriptionProperty to the MyLineItem class.
private string widgetDescriptionProperty;
Add a constructor for the new class. Make this constructor call the constructor for the base class, and set a value for the new member variable. For this example, set the default value of widgetDescriptionProperty to the empty string.
public MyLineItem() : base() { this.widgetDescriptionProperty = ""; }
Add a public property to expose the private member variable. For this example, name the property WidgetDescriptionProperty.
public string WidgetDescriptionProperty { }
Add a get accessor for the new property. Within the get accessor, return the value of the new member variable.
get { return this.widgetDescriptionProperty; }
Add a set accessor for the new property. Within the set accessor, add any necessary validation code, call the SetDirty method, and then set the value of the new member variable.
Note
The SetDirty method updates date/time stamps and performs certain optimizations.
Note
If you map the new property to a column in a database, then the property must have a set accessor.
set { if (value != null) { value = value.Trim(); } SetDirty(value); this.widgetDescriptionProperty = value; }
Add a protected constructor for the new class that implements the ISerializable interface. This constructor creates an instance of the new class from serialized data. Make this constructor call the constructor for the base class, and set a value for the new member variable. For this example, look up the value of widgetDescriptionProperty in the serialized data, and set the widgetDescriptionProperty member variable to the value from the serialized data.
protected MyLineItem(SerializationInfo info, StreamingContext context) : base(info, context) { try { widgetDescriptionProperty = info.GetString("widgetDescriptionProperty"); } catch(SerializationException se) { // Handle exceptions here } }
Override the GetObjectData method of the ISerializable interface. Within the method, call the GetObjectData method on the base class, and then add the value of the new member variable to the serialized data. Add the appropriate security attribute to the method. For this example, add the value of widgetDescriptionProperty to the serialized data.
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("widgetDescriptionProperty", widgetDescriptionProperty); }
Example
The following code shows the complete example of extending the LineItem class to add the widgetDescriptionProperty property.
using System;
using System.Runtime.Serialization;
using System.Security.Permissions;
using Microsoft.CommerceServer.Runtime.Orders;
namespace MyOrdersClasses
{
[Serializable]
public class MyLineItem : LineItem
{
private string widgetDescriptionProperty;
public MyLineItem() : base()
{
this.widgetDescriptionProperty = "";
}
public string WidgetDescriptionProperty
{
set
{
if (value != null)
{
value = value.Trim();
}
SetDirty(value);
this.widgetDescriptionProperty = value;
}
get
{
return this.widgetDescriptionProperty;
}
}
protected MyLineItem(SerializationInfo info, StreamingContext context) : base(info, context)
{
try
{
widgetDescriptionProperty = info.GetString("widgetDescriptionProperty");
}
catch(SerializationException se)
{
// Handle exceptions here.
}
}
// This is the minimum recommended security demand for GetObjectData.
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
base.GetObjectData(info, context);
info.AddValue("widgetDescriptionProperty", widgetDescriptionProperty);
}
}
} // End namespace MyOrdersClasses
See Also
Other Resources
How to Integrate a Derived Class with the Orders System
How to Add a Weakly Typed Indexer Property to an Orders Class