我正在使用IronPython,我知道如何将类中的方法暴露给脚本的范围:
m_scope.SetVariable("log", new Action<string>(Log));
public void Log(string a)
{
Console.WriteLine(a);
}
但是,每次我想使用反射来加速进程时,不是调用SetVariable
。所以,我创建了一个名为ScriptMethodAttribute
的属性:
public sealed class ScriptMethodAttribute : Attribute
{
public string Name { get; private set; }
public ScriptMethodAttribute(string name)
{
Name = name;
}
}
这样,我可以在我的类中定义脚本使用的方法,如下所示:
[ScriptMethod("log")]
public void Log(string a)
{
Console.WriteLine(a);
}
现在我想在每个使用此属性的方法上调用SetVariable来加速进程。但是,这似乎不起作用。
这是一个返回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));
}
这位于我的脚本的类构造函数中:
foreach (var a in Reflector.FindMethodsByAttribute<ScriptMethodAttribute>())
{
Action action = (Action)Delegate.CreateDelegate(typeof(Action), this, a.Item2);
m_scope.SetVariable(a.Item1.Name, action);
}
我收到以下例外:
System.ArgumentException: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
我猜它是因为我必须在Action构造函数中包含所需的类型,但我不知道如何从MethodInfo
类中获取它们。
答案 0 :(得分:0)
要使用一个参数处理方法,可以使用以下代码:
var parameters = methodInfo.GetParameters().Select(p => p.ParameterType).ToArray();
var delegateType = typeof(Action<>).MakeGenericType(parameters);
var action = methodInfo.CreateDelegate(delegateType, this);
// Now you can call m_scope.SetVariable with action
如果要处理具有任意数量参数的方法,事情变得更加棘手,因为您需要根据parameters
数组中的元素数添加一些分支。如果有两个元素,那么您需要使用Action<,>
而不是Action<>
,如果有三个则需要使用Action<,,>
,依此类推。
一种不那么优雅但快速的方法是使用每种类型的Action预分配数组:
private Type[] DelegateTypes = new[]
{
typeof (Action),
typeof (Action<>),
typeof (Action<,>),
typeof (Action<,,>),
typeof (Action<,,,>),
typeof (Action<,,,,>),
typeof (Action<,,,,,>),
typeof (Action<,,,,,,>),
typeof (Action<,,,,,,,>),
typeof (Action<,,,,,,,,>),
typeof (Action<,,,,,,,,,>),
typeof (Action<,,,,,,,,,,>),
typeof (Action<,,,,,,,,,,,>),
typeof (Action<,,,,,,,,,,,,>),
typeof (Action<,,,,,,,,,,,,,>),
typeof (Action<,,,,,,,,,,,,,,>),
typeof (Action<,,,,,,,,,,,,,,,>)
};
从那里,只需访问数组的正确索引,具体取决于您的参数数量:
Type delegateType;
if (parameters.Length == 0)
delegateType = DelegateTypes[0];
else
delegateType = DelegateTypes[parameters.Length].MakeGenericType(parameters);