[英]IronPython - Exposing methods using reflection
我正在使用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
類中獲取它們。
要使用一個參數處理方法,可以使用以下代碼:
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);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.