Set/Get pad by name

vl

#1

Hi devvvs

I’ve been following the thread about auto serialisation

I read with interest @gregsn post extolling the virtues of manual serialisation. I think it all makes sense but I have implemented this and created a huge web of XElement nodes, quite clunky to patch and a lot of work to keep updated. (Unless I’m just doing it in a stupid way… very possible).

My feature request is for functionality that would allow a hybrid approach, semi-automated serialisation.

-The functionality would be special SetByName and GetByName member operations that could be called for any object.
-They sift for the name of a pad in a given object and either Set or Get the value with a success bang. A special alternative to using pins.
-If the pad doesn’t exist they don’t succeed.

  • This would allow me to build a much neater serialisation patch that takes a spread of x paths, a spread of pad names, a spread of values and an object and gives you a set object
    -If versions have changed you can use the success pin to see what has failed and act accordingly.

It might look like this?

Further thoughts
-I think a ‘ListPadNames’ operation might also be handy.
-End user can of course write more complicated versioning if they want. Eg with a diff.xml type setup that remembers old names.
-The failure conditions could distinguish between failing due to impossible parse or failing due to not finding a matching pad name
-You could expose internal parts of this to allow optimisation. Eg sifting for pad names creates an ‘object memory map’ and that whats applied to some raw form of the object to update the value. You could optimise by doing the sifting only once when you first run the program and then using the memory map after that.

Whaddya think?


#2

yes, that is indeed by far the most time consuming process when building your own serializer for big data types. me and @seltzdesign had the same task in the past weeks.

now that you say it, you can do that already with the System.Reflection namespace. it allows to build getter and setter methods by field name. only thing is that the internal name of a vl pad has ‘_’ for each space. this might be a start:


#3

i still don’t subscribe to the “always try to build your own serializer” at all, and the screenshots you show only strengthens that notion. this is just insane, especially if you have to do this just to opt-in (or opt-out) a few members.

but since you opened a new can here (reflections), I will treat this thread with an open mind.

for a starter, it might be wiser to use fasterflect or some other IL-generating reflection-lib right away, because (vanilla) reflections and realtime tend to be not the best of friends.

as a side-note I found it tremendously insightful to output the vl objects into the vvvv world, and use Visual Studio in debug mode to fully inspect the vl-generated objects.

edit: found this on my harddrive

	public static class ReflectionUtility
{
	public static Func<object, object> CompileGetter(this FieldInfo field)
    {
	    string methodName = field.ReflectedType.FullName + ".get_" + field.Name;
    	DynamicMethod setterMethod = new DynamicMethod(methodName, typeof(object), new[] { typeof(object) }, true);
        ILGenerator gen = setterMethod.GetILGenerator();
    	if (field.IsStatic)
	    {
    	    gen.Emit(OpCodes.Ldsfld, field);
        	gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Box, field.FieldType);
        }
	    else
    	{
        	gen.Emit(OpCodes.Ldarg_0);
            gen.Emit(OpCodes.Castclass, field.DeclaringType);
	        gen.Emit(OpCodes.Ldfld, field);
    	    gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Box, field.FieldType);
        }
	    gen.Emit(OpCodes.Ret);
    	return (Func<object, object>)setterMethod.CreateDelegate(typeof(Func<object, object>));
	}

	public static Action<object, object> CompileSetter(this FieldInfo field)
	{
    	string methodName = field.ReflectedType.FullName + ".set_" + field.Name;
    	DynamicMethod setterMethod = new DynamicMethod(methodName, null, new[] { typeof(object), typeof(object) }, true);
    	ILGenerator gen = setterMethod.GetILGenerator();
    	if (field.IsStatic)
    	{
        	gen.Emit(OpCodes.Ldarg_1);
            gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Unbox_Any, field.FieldType);
	        gen.Emit(OpCodes.Stsfld, field);
    	}
        else
	    {
    	    gen.Emit(OpCodes.Ldarg_0);
        	gen.Emit(OpCodes.Castclass, field.DeclaringType);
            gen.Emit(OpCodes.Ldarg_1);
	        gen.Emit(field.FieldType.IsClass ? OpCodes.Castclass : OpCodes.Unbox_Any, field.FieldType);
    	    gen.Emit(OpCodes.Stfld, field);
    	}
    	gen.Emit(OpCodes.Ret);
    	return (Action<object, object>)setterMethod.CreateDelegate(typeof(Action<object, object>));
    }
}

this was part of that abandoned experiment:
ObjectTypeCheck.7z (8.2 KB)


#4

@tobyk btw, to avoid this yellow spider web, make a utility operation and reuse the same input pin on many places, they will all have the same data connecte to the pin outside:


#5

@Velcrome @Tonfilm I don’t know if I’m yet up to importing a .net library to VL but I’ll give it a shot.

@Tonfilm At the time I made this I didn’t know the duplicate input pin trick. I do now but it’s the spiderweb of connections at the bottom I’m trying to work around.