Answer:
Dynamic Properties!
Here is a NUnit test I wrote to confirm my approach:
First, the C#:
/// <summary>AggregateQuery Test</summary>
/// <remarks>
/// Demonstrates an aggregate query using DynamicTypes
/// and creation of a dynamic property so that we can
/// data bind to the column (field) returned from the query.
/// </remarks>
[Test]
public void AggregateQueryTest() {
Type DynType;
DynType = DynamicEntityTypeBuilder.CreateType("DynTypeTest", "Default");
// Query for count of Employees with a LastName before 'K'
IEntityQuery qry;
qry = new PassthruRdbQuery(DynType,
"SELECT count(*) as TotalEmps FROM Employee WHERE LastName < 'K'");
EntityList<DynamicEntity> entities =
PersistenceManager.DefaultManager.GetEntities<DynamicEntity>(qry);
// Add a property descriptor to get a column we want through data binding
AddTotalEmpsPropertyDescriptor(DynType, entities);
}
/// <summary>
/// Add a "TotalEmps" dynamic property for a dynamic type
/// with an integer "TotalEmps" field.
/// </summary>
private void AddTotalEmpsPropertyDescriptor(Type pDynType,
EntityList<DynamicEntity> pEntities) {
// This MUST become a private property list
// because the next time an instance of
// DynamicEntity will have completely different columns
// and we don't want the pd we're about to add to be
// hanging around!
pEntities.UsesGlobalPropertyDescriptors = false;
// Make a dynamic property descriptor for TotalEmps
AdaptedPropertyDescriptor pd =
new AdaptedPropertyDescriptor("TotalEmps", pDynType, typeof(int), _get_TotalEmps, null);
// Add it to the list's PropertyDescriptors
pEntities.PropertyDescriptors.Add(pd);
// Confirm that the "getter" delegate returns the same value
// as the field inside the entity.
// That means it will work when we data bind to it.
Assert.AreEqual(pEntities[0]["TotalEmps"], _get_TotalEmps(pEntities[0]));
}
/// <summary>
/// The "getterdelegate" used within a dynamic property for a dynamic type
/// with an integer "TotalEmps" field.
/// </summary>
private object _get_TotalEmps(object pEntity) {
return (int) ((DynamicEntity) pEntity)["TotalEmps"];
}
Now the VB (which I have converted but not tested):
''' <summary>AggregateQuery Test</summary>
''' <remarks>
''' Demonstrates an aggregate query using DynamicTypes
''' and creation of a dynamic property so that we can
''' data bind to the column (field) returned from the query.
''' </remarks>
<Test> _
Public Sub AggregateQueryTest()
Dim DynType As Type
DynType = DynamicEntityTypeBuilder.CreateType("DynTypeTest", "Default")
' Query for count of Employees with a LastName before 'K'
Dim qry As IEntityQuery
qry = New PassthruRdbQuery(DynType, _
"SELECT count(*) as TotalEmps FROM Employee WHERE LastName < 'K'")
Dim entities As EntityList(Of DynamicEntity) = _
PersistenceManager.DefaultManager.GetEntities(Of DynamicEntity)(qry)
' Add a property descriptor to get a column we want through data binding
AddTotalEmpsPropertyDescriptor(DynType, entities)
End Sub
''' <summary>
''' Add a "TotalEmps" dynamic property for a dynamic type
''' with an integer "TotalEmps" field.
''' </summary>
Private Sub AddTotalEmpsPropertyDescriptor( _
ByVal pDynType As Type, ByVal pEntities As EntityList(Of DynamicEntity))
' This MUST become a private property list
' because next time an instance of
' DynamicEntity will have completely different columns
' and we don't want the pd we're about to add to be
' hanging around!
pEntities.UsesGlobalPropertyDescriptors = False
' Make a dynamic property descriptor for TotalEmps
Dim pd As New AdaptedPropertyDescriptor( _
"TotalEmps", pDynType, GetType(Integer), AddressOf _get_TotalEmps, Nothing)
' Add it to the list's PropertyDescriptors
pEntities.PropertyDescriptors.Add(pd)
' Confirm that the "getter" delegate returns the same value
' as the field inside the entity.
' That means it will work when we data bind to it.
Assert.AreEqual(pEntities(0)("TotalEmps"), _get_TotalEmps(pEntities(0)))
End Sub
''' <summary>
''' The "getterdelegate" used within a dynamic property for a dynamic type
''' with an integer "TotalEmps" field.
''' </summary>
Private Function _get_TotalEmps(ByVal pEntity As Object) As Object
Return CInt(Fix((CType(pEntity, DynamicEntity))("TotalEmps")))
End Function
Enjoy !