This article describes how to write efficient DisplayDrivers for your Parts so that expensive code is only executed when the shape is actually displayed.
protected override DriverResult Display(MyPart part, string displayType, dynamic shapeHelper)
{
// return the shape
return ContentShape("Parts_MyPart", () => {
// do computations here
return shapeHelper.Parts_MyPart();
});
}
Now I'd like to make a Part that returns multiple DriverResults using the Combine
method, with each DriverResult containing mostly the same data, which is fetched from the database. The problem is I can't think of a good way to make it efficient, since Combine
doesn't take a Func parameter.
protected override DriverResult Display(MyPart part, string displayType, dynamic shapeHelper)
{
var data = ... // expensive query specific to the part
return Combined(
ContentShape("Parts_MyPart_A", () => shapeHelper.Parts_MyPart_A(
Data: data
)),
ContentShape("Parts_MyPart_B", () => shapeHelper.Parts_MyPart_B(
Data: data
)),
ContentShape("Pars_MyPart_C", ...
);
}
Can I achieve the same result so that the query is not executed if nothing is displayed and only executed once if multiple shapes are displayed?
I want to do this so I can display the same data on a ContentItem's Detail in different zones with different markup and styling. An alternative approach could be to return one shape that in turn pushes other shapes into different zones but then I would lose the ability to use Placement to control each of them individually.
I'd probably add a lazy field to your Part.
public class MyPart : ContentPart {
internal readonly LazyField<CustomData> CustomDataField = new LazyField<CustomData>();
public CustomData CustomData {
get { return CustomDataField.Value; }
}
}
public class CustomData {
...
}
public class MyPartHandler : ContentPartHandler {
private ICustomService _customService;
public MyPartHandler(ICustomService customService){
_customService = customService;
OnActivated<MyPart>(Initialize);
}
private void Initialize(ActivatedContentContext context, MyPart part){
part.CustomDataField.Loader(() => {
return _customService.Get(part.ContentItem.Id);
});
}
}
It will only be calculated if it is loaded and all the shapes will share the calculated value.