![](/img/trans.png)
[英]Is it possible to call the explicit interface implementation of the base class in c#?
[英]How to reflect on C# explicit interface implementation from the call stack?
是否可以考虑调用堆栈中的显式接口实现? 我想使用此信息在界面本身上查找属性。
给出以下代码:
interface IFoo
{
void Test();
}
class Foo : IFoo
{
void IFoo.Test() { Program.Trace(); }
}
class Program
{
static void Main(string[] args)
{
IFoo f = new Foo();
f.Test();
}
public static void Trace()
{
var method = new StackTrace(1, false).GetFrame(0).GetMethod();
// method.???
}
}
具体来说,在Trace()中,我希望能够从method
转到typeof(IFoo)
。
在监视窗口中,如果我查看method.ToString()
它将为我提供Void InterfaceReflection.IFoo.Test()
(InterfaceReflection是我的程序集的名称)。
如何从那里进入typeof(IFoo)
? 我必须从程序集本身使用基于名称的类型查找,还是在MethodBase
某个位置隐藏Type IFoo
?
更新:
这是最终的解决方案,感谢Kyte
public static void Trace()
{
var method = new StackTrace(1, false).GetFrame(0).GetMethod();
var parts = method.Name.Split('.');
var iname = parts[parts.Length - 2];
var itype = method.DeclaringType.GetInterface(iname);
}
itype
将具有实现方法的接口类型。 这仅适用于显式的接口实现,但这正是我所需要的。 现在,我可以使用itype
来查询附加到实际接口类型的属性。
感谢大家的帮助。
在VS2010上进行测试,我发现DeclaringType,它获取包含该方法的对象类型,从那里您可以将接口作为Type对象获取。
public static void Trace() {
var stack = new StackTrace(1, true);
var frame = stack.GetFrame(0);
var method = frame.GetMethod();
var type = method.DeclaringType;
Console.WriteLine(type);
foreach (var i in type.GetInterfaces()) {
Console.WriteLine(i);
}
}
返回值:
TestConsole.Foo
TestConsole.IFoo
(我称这个项目为TestConsole)
method
将是System.Reflection.RuntimeMethodInfo
,这是从System.Reflect.MethodBase
派生的类。 您可以例如在其上调用Invoke()
(尽管如果在获取它的那一点上调用了Invoke()
,那么这将导致无限递归并最终由于溢出堆栈而消失)。
在其上调用ToString()
将返回完全限定的名称。 您是否将项目称为InterfaceReflection?
不知道您想要什么。
编辑:好的,现在我知道了。 要查找声明类型,请查看DeclaringType属性,这将返回在其上声明了该方法的类(可以是在其上调用的类或基类):
到目前为止,到目前为止,这很容易为Foo返回Type对象。
现在,请注意一点,因为您关心的是在其上声明的接口。 但是,可能有多个接口定义了具有完全相同签名的方法,这意味着一个简单的问题:“如果它来自某个接口,那么该接口是什么?” 并非总是有一个答案。
可能有一种更整洁的方法,但是我能想到的就是在从DeclaringType
获得的Type
对象上调用GetInterfaces()
,然后寻找名称与方法签名匹配的对象。
我不想设定太多,但是在这种情况下,由于Foo和Program是相互依赖的,因此您似乎引起了一些混乱。 通常,我会认为Program会以某种方式“拥有” Foo(这与Program无关),它负责设置委托,因此可以避免反思……您的设置方式是,Foo拥有“(实际上,我想取决于它可能更准确)以某种方式编程(因为它很难调用其Program.Trace()),而程序以某种方式“拥有” Foo(因为它控制了实例)。
我不知道这是否适用于您的特定场景,但似乎事件类型的操作可能更有意义,并且可以更轻松地处理通信。
预计到达时间:代码示例:
public interface IFoo
{
event EventHandler Testing;
void Test();
}
public class Foo : IFoo
{
public event EventHandler Testing;
protected void OnTesting(EventArgs e)
{
if (Testing != null)
Testing(this, e);
}
public void Test()
{
OnTesting(EventArgs.Empty);
}
}
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
IFoo f = new Foo();
f.Testing += new EventHandler(f_Testing);
f.Test();
}
static void f_Testing(object sender, EventArgs e)
{
IFoo foo = sender as IFoo;
if (foo != null)
{
//...
}
}
}
不过,我可能会误解您的问题。
我认为.NET将全名附加到MethodInfo.Name属性的前面,以便它对每个方法都有唯一的名称。 考虑到:
interface IFoo
{
void Test();
}
interface IFoo2
{
void Test();
}
class Foo : IFoo, IFoo2
{
void IFoo.Test() { Trace(); }
void IFoo2.Test() { Trace(); }
}
在这种情况下, typeof(Foo).GetMethods()
将返回两个Test()
方法,但是它们的名称会发生冲突,因此我猜想它们会附加接口名称以使其唯一吗?
MethodInfo.DeclaringType
返回包含实现的类型。 因此,如果IFoo实际上是某个基本类型而不是一个接口,并且那里有一个基本方法声明,则.DeclaringType
将返回该基类的类型。
有趣的是,我似乎也无法在MethodInfo的任何地方找到实际的接口名称,因此我想您必须按名称查找它,例如:
public static void Trace()
{
var method = new System.Diagnostics.StackTrace(1, false).GetFrame(0).GetMethod();
var fromType = method.DeclaringType;
if (method.Name.Contains("."))
{
var iname = method.Name.Substring(0, method.Name.LastIndexOf('.'));
fromType = Type.GetType(iname); // fromType is now IFoo.
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.