While working on the planned 3D tiles 1.1 upgrade for metadata in Unity, I wondered if we could integrate Generics in any way to simplify the API. In particular, I thought it might be useful to have a CesiumPropertyTableProperty.GetAs<T> function, to avoid the individual GetBoolean, GetString, etc. calls we have to write for every possible type.
The idea is to implement the GetAs<T> on the C++ side with templating. Then, in ConfigureReinterop, we can list every single type of T that we expect to handle. Currently, Reinterop takes the generic function, and turns it into a template on the C++ side:
template <typename T>
T GetAs(const T& value) const;
Then, it has a bunch of different calls matching the expected types, and it specializes the template in the .cpp file. Aside from an erroneous #include <T.h>, it's actually possible to compile the native code with a template<typename T> GetAs<T> C++ implementation. However...it doesn't completely work. Unity complains on the C# about CesiumPropertyTableProperty-generated.cs, because it generates the partial method like so:
public partial T GetAs(T value)
{
unsafe
{
if (this._implementation == null || this._implementation.IsInvalid)
throw new NotImplementedException("The native implementation is missing so GetAs cannot be invoked. This may be caused by a missing call to CreateImplementation in one of your constructors, or it may be that the entire native implementation shared library is missing or out of date.");
var result = DotNet_CesiumForUnity_CesiumPropertyTableProperty_GetAs(Reinterop.ObjectHandleUtility.CreateHandle(this), _implementation, value);
return result;
}
}
As @kring noted:
So the immediate problem is that it's not declared as a generic method at all. But the bigger problem is that we can't write a single implementation of this method that works across types.
Ultimately we decided it's better to have the individual Get___ functions for usability reasons outside of Reinterop. But a solution that @kring proposed, if we need it in the future:
It's not totally impossible. You can use a generic class with a static field as a kind of map with C# generics.
something like:
class TypeMapThingo<T> {
static int SomeValue;
}
TypeMapThingo<int>.SomeValue = 4;
TypeMapThing<float>.SomeValue = 5;
so in this case SomeValue could be a delegate that is used to dispatch to the correct C++ function pointer.
But that'd definitely takes some changes to Reinterop
While working on the planned 3D tiles 1.1 upgrade for metadata in Unity, I wondered if we could integrate Generics in any way to simplify the API. In particular, I thought it might be useful to have a
CesiumPropertyTableProperty.GetAs<T>
function, to avoid the individualGetBoolean
,GetString
, etc. calls we have to write for every possible type.The idea is to implement the
GetAs<T>
on the C++ side with templating. Then, inConfigureReinterop
, we can list every single type ofT
that we expect to handle. Currently, Reinterop takes the generic function, and turns it into a template on the C++ side:Then, it has a bunch of different calls matching the expected types, and it specializes the template in the .cpp file. Aside from an erroneous
#include <T.h>
, it's actually possible to compile the native code with atemplate<typename T> GetAs<T>
C++ implementation. However...it doesn't completely work. Unity complains on the C# aboutCesiumPropertyTableProperty-generated.cs
, because it generates the partial method like so:As @kring noted:
Ultimately we decided it's better to have the individual
Get___
functions for usability reasons outside of Reinterop. But a solution that @kring proposed, if we need it in the future: