lundi 25 juillet 2016

Creating a Func

After much research and searching on SO; I've failed to find an answer that encompasses my specific situation. I wish to add modding capabilities to my project; currently I use a 3rd-party C# API which can convert scripts written in a particular interpreted language (specifically the functions in these scripts) into C# delegates.

Is there a way to wrap all of the delegates I get from the 3rd party API, into the a generic Func Delegate? My thoughts (in code) follow...

//The goal signature for all 'imported' delegates
public delegate object GenericSignature(object[] args);

//A fictional example...
public class Program
{
    public static void Main()
    {
        GenericSignature desiredFunc = GenerateFromArbitraryMethod(Program.FictionalArbitraryMethod);
        object retVal = desiredFunc(1, new object(), "If only this worked");
    }

    public static FictionalArbitraryMethod(int num, object stuff, string name) { //code from mod author would be here }
}

//Attempt #1
//If my assumptions about Delegate.CreateDelegate() is correct, this probably will not work... 
public GenericSignature GenerateFromArbitraryMethod(Delegate d) {
    MethodInfo mInfo = d.Method;
    return (GenericSignature) Delegate.CreateDelegate(typeof(GenericSignature), mInfo);
}

//Attempt #2
public GenericSignature GenerateFromArbitraryMethod(Delegate d) {
    MethodInfo mInfo = d.Method;

    //seems a bit... better?; I can do some validation, but how do I actually call the 
    //function represented by MethodInfo since it's signature is arbitrary?
    return delegate(object[] args) {

        ParameterInfo[] pInfo = mInfo.GetParameters();
        if(args.length != pInfo.length) {
             throw new Exception("Argument count does not match");
        }

        for(int i = 0; i < args.length; i++) {
             if(pInfo[i].ParameterType != args[i].GetType()) {
                 throw new Exception("Incorrect Type for argument");
             } 
        }

        //At a loss of how to do the following; fake psuedo-code follows
        /*
        Foreach(object currentArg in arg) {
           d.AppendArgAndCast(currentArg); 
        }
        return d.Call();

        or...

        return d(EachOrUnpackAndCast(args));
        */

    };
}

Apologies if there are any errors in the syntax; I'm mainly trying to get across the concept of what I'm trying to achieve. Some additional notes:

EDIT: 1. My project is targeting .NET 2.0 (and possibly... a subset of .NET 3.5?) Not 100% sure of what is supported in Unity.

  1. It is ok if any suggested solution is 'slow/heavy' due to heavy use of reflection; as long as I can generate a delegate, which I can cache and just call many, many times (to amortize the initial delegate creation cost)




Aucun commentaire:

Enregistrer un commentaire