lundi 17 octobre 2016

IronPython - Exposing methods using reflection

I'm using IronPython and I know how to expose methods from my class to the script's scope:

m_scope.SetVariable("log", new Action<string>(Log));

public void Log(string a)
{
    Console.WriteLine(a);
}

However, instead of calling SetVariable everytime I want to speed up the process using reflection. So, I created an attribute called ScriptMethodAttribute:

public sealed class ScriptMethodAttribute : Attribute
{
    public string Name { get; private set; }

    public ScriptMethodAttribute(string name)
    {
        Name = name;
    }
}

That way, I can define methods inside my class for the script to use, like so:

[ScriptMethod("log")]
public void Log(string a)
{
    Console.WriteLine(a);
}

Now I want to call SetVariable on every method that uses this attribute to speed up the process. However, that doesn't seem to work.

This is a utility method that returns a list of Tuple<ScriptMethodAttribute, MethodInfo.

public static IEnumerable<Tuple<TAttribute, MethodInfo>> FindMethodsByAttribute<TAttribute>()
        where TAttribute : Attribute
{
    return (from method in AppDomain.CurrentDomain.GetAssemblies()
                    .Where(assembly => !assembly.GlobalAssemblyCache)
                    .SelectMany(assembly => assembly.GetTypes())
                    .SelectMany(type => type.GetMethods())
                let attribute = Attribute.GetCustomAttribute(method, typeof(TAttribute), false) as TAttribute
                where attribute != null
                select new Tuple<TAttribute, MethodInfo>(attribute, method));
}

This is located in my script's class constructor:

foreach (var a in Reflector.FindMethodsByAttribute<ScriptMethodAttribute>())
{
    Action action = (Action)Delegate.CreateDelegate(typeof(Action), this, a.Item2);

    m_scope.SetVariable(a.Item1.Name, action);
}

I'm receiving the following exception:

System.ArgumentException: Cannot bind to the target method because its signature or security transparency is            not compatible with that of the delegate type.

I'm guessing it's because I have to include the required types in the Action constructor, but I don't know how to get them from the MethodInfo class.





Aucun commentaire:

Enregistrer un commentaire