Using member of GH_PersistentParam<T> without knowing <T>

Hi,

I want to clear the persistent data in one of my custom components:

var param = Params.Input[0];      // is GH_Param<T>
???                               // Casting to GH_PersistentParam<T> for the following action
if (param != null) {
    param.PersistentData.Clear();
    param.OnObjectChanged(GH_ObjectEventType.PersistentData);
}

My current solution casts to every possible class (Param_Curve, Param_Surface, …) until success. But as I’m not using <T> at all, I guess there is a simpler, less performance / maintenance prone method.

I know it’s a general C# / Generics issue but maybe someone here can help. Thanks!

Try accessing the PersistentData field via Reflection. You can use a utility method in Grasshopper.Utility for this:

IGH_Param param = Component.Params.Input[0];
object obj = Grasshopper.Utility.InvokeGetterSafe(param, "PersistentData");
if (obj == null) return;

IGH_Structure persistent = obj as IGH_Structure;
if (persistent == null) return;

A = persistent.DataDescription(true, true);
1 Like

Thanks. Seems to work! And it can be put in a nice one-liner:

((IGH_Structure) Utility.InvokeGetterSafe(param, "PersistentData"))?.Clear();

(IGH_Structre) will throw if the instance is not of the correct type, the as keyword will not. Since you’re combining it with the ?. operator, as would make a lot more sense.

Yes. And with the following method, it is also possible to SET the persistent data:

public static bool SetPeristentData(IGH_Param param, IGH_Structure tree) {
    if (param == null || param.Kind != GH_ParamKind.floating) return false;

    var tree = (IGH_Structure) Utility.InvokeGetterSafe(param, "PersistentData");
    if (tree == null) return false;

    tree.Clear();
    param.ClearData();
    param.AddVolatileDataTree(tree);
    Utility.InvokeMethodSafe(tree, "MergeStructure", param.VolatileData);	

    return true;
}

(Ab-) using the volatile data for this has the great advantage, that all the heavy casting logic is included for free (has the same flexibility like a “wired” connection, and yes <T> is not needed too - :sweat:) . Thanks again for your hint. Saved me some hours of head-aching Trial&Error!
Best regards.