This is a potential opinion on how strongly-typed XP should be defined in a C# project. It would include adding code to the catalyst library and creating a guide for solutions. The goals are
Make it more likely XP will be consistent within resources and avoid indexing issues
Make it easy to take an inventory of all XP used within a project
Reduce boilerplate code
The framework
Currently, strongly-typed xp requires code like below for every resource.
// Boilerplate
public class OrderCalculateResponseWithXp : OrderCalculateResponse<OrderCalculateResponseXp, LineItemOverrideWithXp> { }
public class LineItemOverrideWithXp : LineItemOverride<AdHocProductWithXp> { }
public class AdHocProductWithXp : AdHocProduct<AdHocProductXp> { }
// boilerplate if empty, but still required
public class OrderCalculateResponseXp { }
// Not Boilerplate
public class AdHocProductXp
{
// put xp here
}
The first suggestion is to put all the boilerplate code above into a library like Catalyst so that the meaningful code - definitions of XP - are clear and unobstructed. Classes like AdHocProductXp would be defined in the library as empty partials, with the solution also defining them as partials and including the xp details.
The second suggestion is to define a convention of putting all the partial <Resource>Xp classes in a single file called Xp.cs. Putting them all in one file makes it easy to be confident there are no other xp definitions hiding in other parts of the project. It also means that source control will produce merge conflicts if two people edit xp simultaneously. This is actually a benefit because it means changes in xp are considered in the context of all existing xp. This reduces the likelihood of conflicting or duplicated definitions. It would look something like this
public class OrderCalculateResponseWithXp : OrderCalculateResponse<OrderCalculateResponseXp, LineItemOverrideWithXp> { }
public class LineItemOverrideWithXp : LineItemOverride<AdHocProductWithXp> { }
public class AdHocProductWithXp : AdHocProduct<AdHocProductXp> { }
...
Xp.cs
public partial class OrderCalculateResponseXp { }
public partial class AdHocProductXp { }
...
New client project code
Xp.cs
public partial class AdHocProductXp
{
public string MyProperty { get; set; }
}
...
MyServerSideCommand.cs
// same as before, but dev needs to understand the connection between AdHocProductXp and AdHocProductWithXp.
AdHocProductWithXp product = await _oc.AdHocProduct.GetAsync<AdHocProductWithXp>(myID);
Gotchas
Multiple OC models will need to be mapped to a single xp schema. A good example are the Product and BuyerProduct models (which serve the same underlying data from two different endpoints). This is strictly necessary. Formalizing all the examples in a framework could reduce coding errors.
public class BuyerProductWithXp : BuyerProduct<ProductXp> { }
public class ProductWithXp: Product<ProductXp> { }
A single OC model might reasonably be mapped to multiple different xp schemas. A good example is the singular Address model (which is used for multiple endpoints). This is not strictly necessary, but more open to opinions. The framework would try to create a generally good opinion but would limit options. For example, what if Admin and Supplier addresses should have the same xp schema? Of course, devs can always define their own classes outside the framework.
public class BuyerAddressWithXp : Address<BuyerAddressXp> { }
public class SupplierAddressWithXp : Address<SupplierAddressXp> { }
public class AdminAddressWithXp : Address<AdminAddressXp> { }
Intro
This is a potential opinion on how strongly-typed XP should be defined in a C# project. It would include adding code to the catalyst library and creating a guide for solutions. The goals are
The framework
Currently, strongly-typed xp requires code like below for every resource.
The first suggestion is to put all the boilerplate code above into a library like Catalyst so that the meaningful code - definitions of XP - are clear and unobstructed. Classes like
AdHocProductXp
would be defined in the library as empty partials, with the solution also defining them as partials and including the xp details.The second suggestion is to define a convention of putting all the partial
<Resource>Xp
classes in a single file called Xp.cs. Putting them all in one file makes it easy to be confident there are no other xp definitions hiding in other parts of the project. It also means that source control will produce merge conflicts if two people edit xp simultaneously. This is actually a benefit because it means changes in xp are considered in the context of all existing xp. This reduces the likelihood of conflicting or duplicated definitions. It would look something like thishttps://github.com/ordercloud-api/dotnet-middleware/blob/dev/Customer.OrderCloud.Common/Models/Xp.cs
New library code
ModelWithXp.cs
Xp.cs
New client project code
Xp.cs
MyServerSideCommand.cs
Gotchas