Jer*_*ine 314 .net c# reflection private-methods
我的类中有一组私有方法,我需要根据输入值动态调用一个.调用代码和目标方法都在同一个实例中.代码如下所示:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType);
dynMethod.Invoke(this, new object[] { methodParams });
Run Code Online (Sandbox Code Playgroud)
在这种情况下,GetMethod()
不会返回私有方法.什么BindingFlags
我需要提供以GetMethod()
使其能找到私有方法?
wpr*_*prl 481
只需更改代码即可使用接受BindingFlags 的重载版本GetMethod
:
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
dynMethod.Invoke(this, new object[] { methodParams });
Run Code Online (Sandbox Code Playgroud)
Jer*_*ine 66
BindingFlags.NonPublic
不会自行返回任何结果.事实证明,结合它可以解决BindingFlags.Instance
问题.
MethodInfo dynMethod = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
Run Code Online (Sandbox Code Playgroud)
cod*_*k3y 51
如果您真的想让自己陷入困境,可以通过编写扩展方法来更轻松地执行:
static class AccessExtensions
{
public static object call(this object o, string methodName, params object[] args)
{
var mi = o.GetType ().GetMethod (methodName, System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance );
if (mi != null) {
return mi.Invoke (o, args);
}
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
class Counter
{
public int count { get; private set; }
void incr(int value) { count += value; }
}
[Test]
public void making_questionable_life_choices()
{
Counter c = new Counter ();
c.call ("incr", 2); // "incr" is private !
c.call ("incr", 3);
Assert.AreEqual (5, c.count);
}
Run Code Online (Sandbox Code Playgroud)
Owe*_*mes 14
Microsoft最近修改了反射API,使得大多数这些答案都过时了.以下内容适用于现代平台(包括Xamarin.Forms和UWP):
obj.GetType().GetTypeInfo().GetDeclaredMethod("MethodName").Invoke(obj, yourArgsHere);
Run Code Online (Sandbox Code Playgroud)
或者作为扩展方法:
public static object InvokeMethod<T>(this T obj, string methodName, params object[] args)
{
var type = typeof(T);
var method = type.GetTypeInfo().GetDeclaredMethod(methodName);
return method.Invoke(obj, args);
}
Run Code Online (Sandbox Code Playgroud)
注意:
如果所需方法在泛型的超类中,obj
则T
必须将其显式设置为超类的类型.
如果方法是异步的,您可以使用await (Task) obj.InvokeMethod(…)
.
Bil*_*l K 10
你绝对相信这不能通过继承吗?反思是解决问题时应该注意的最后一件事,它会使重构,理解代码以及任何自动分析变得更加困难.
看起来你应该只有一个DrawItem1,DrawItem2等类来覆盖你的dynMethod.
私有成员反射破坏了封装原则,从而将您的代码暴露给以下内容:
有这样的情况,当你依赖第三方或者你需要一些不暴露的api时,你必须做一些反思.有些人还使用它来测试他们拥有的一些类,但是他们不想更改接口以仅为测试提供对内部成员的访问.
为了缓解容易中断的问题,最好的方法是通过在连续集成构建中运行的单元测试中测试来检测任何可能的中断.当然,这意味着您始终使用相同的程序集(包含私有成员).如果你使用动态加载和反射,你喜欢玩火,但你总是可以捕获调用可能产生的异常.
在.Net Framework的最新版本中,CreateDelegate在MethodInfo调用时击败因子50:
// The following should be done once since this does some reflection
var method = this.GetType().GetMethod("Draw_" + itemType,
BindingFlags.NonPublic | BindingFlags.Instance);
// Here we create a Func that targets the instance of type which has the
// Draw_ItemType method
var draw = (Func<TInput, Output[]>)_method.CreateDelegate(
typeof(Func<TInput, TOutput[]>), this);
Run Code Online (Sandbox Code Playgroud)
draw
呼叫将比MethodInfo.Invoke
使用draw
标准快50倍左右Func
:
var res = draw(methodParams);
Run Code Online (Sandbox Code Playgroud)
查看我的这篇文章,看看不同方法调用的基准
归档时间: |
|
查看次数: |
157729 次 |
最近记录: |