.net 如何找到声明方法的接口

.net 如何找到声明方法的接口,.net,reflection,unity-container,enterprise-library,system.reflection,.net,Reflection,Unity Container,Enterprise Library,System.reflection,我用Unity进行拦截。因为我有很多接口,我不得不使用VirtualMethodInterceptor。在我的行为中,我只想在调用的方法在具有特殊属性的特定类型的接口中声明时做出反应。我原以为MethodBase.DeclaringType可以解决我的问题,但它的行为与我希望的不同。它返回实现类型 我同意这是有道理的,因为该方法可以在多个接口中声明,但应该有一种方法可以轻松地获得它们的列表。不幸的是,我还没有找到它 小样本显示我的问题 public interface ISample {

我用Unity进行拦截。因为我有很多接口,我不得不使用VirtualMethodInterceptor。在我的行为中,我只想在调用的方法在具有特殊属性的特定类型的接口中声明时做出反应。我原以为MethodBase.DeclaringType可以解决我的问题,但它的行为与我希望的不同。它返回实现类型

我同意这是有道理的,因为该方法可以在多个接口中声明,但应该有一种方法可以轻松地获得它们的列表。不幸的是,我还没有找到它

小样本显示我的问题

public interface ISample
{
    void Do();
}

public class Sample : ISample
{
    public void Do()
    {
    }
}

class Program
{
    static void Main(string[] args)
    {
        var m = typeof(Sample).GetMethod("Do") as MethodBase;
        Console.WriteLine(m.DeclaringType.Name); // Prints "Sample"
    }
}
一个棘手的解决方案:


我能想出的唯一类似于你的解决方案不是那么尴尬

public static bool IsMethodDeclaredInInterface(MethodBase method, Type myInterface)
{
    var methodType = method.DeclaringType;
    var typeFilter = new TypeFilter((t, crit) =>
                                        {
                                            var critTypes = crit as Type[];
                                            return critTypes != null && critTypes.Any(ty => ty.FullName == t.FullName);
                                        });
    var res = methodType.FindInterfaces(typeFilter, new[] {myInterface});
    return res.Length > 0;
}

最终我使用了以下代码:

var interfaces = from i in input.MethodBase.DeclaringType.GetInterfaces()
                 let parameters = input.MethodBase.GetParameters().Select(p=>p.ParameterType).ToArray()
                 where i.GetCustomAttributes(typeof(CustomAttribute), true).Length > 0
                 where i.GetMethod(input.MethodBase.Name, parameters) != null
                 select i;

我认为你一直在列举接口;我还没有看到访问特定接口的方法

此外,如果显式实现接口,可能会出现一个小的边缘情况。在这种情况下,void ISample.Do MethodBase.Name将是完全限定的方法名称,例如MyApp.ISample.Do和not Do

我找到的唯一解决办法是删掉主要信息。例如

string methodName = input.MethodBase.Name;
int methodIndex = methodName.LastIndexOf('.');

if (methodIndex != -1)
{
    methodName = methodName.Substring(methodIndex + 1, 
        methodName.Length - methodIndex - 1);
}

var interfaces = from i in input.MethodBase.DeclaringType.GetInterfaces()
                 let parameters = input.MethodBase.GetParameters().
                     Select(p => p.ParameterType).ToArray()
                 where i.GetCustomAttributes(typeof(CustomAttribute), true).Length > 0
                 where i.GetMethod(methodName, parameters) != null
                 select i;
另外,如果有另一个方法具有相同的名称和签名,那么我不确定如何确定该方法是否是通过接口而不是公共方法调用的

public class Sample : ISample
{
    public void Do()
    {
        // this is a public method
    }

    void ISample.Do()
    {
        // this is the interface implementation
    }
}
我想可能会寻找具有相同名称和签名的其他方法,并通过查看其他MethodBase属性进行区分


也就是说,public void Do将IsHideBySig和IsPublic设置为true,而void为sample。Do将IsFinal、IsVirtual、IsPrivate和IsHideBySig全部设置为true。但我不确定这对所有情况都是足够的。

将您的尴尬解决方案作为答案发布并接受它。笨拙的需求有笨拙的解决方案。但我真的需要枚举所有接口和所有参数吗。我不知道这是否是一个笨拙的要求,但我希望从运行时得到更好的帮助。在我看来,您的解决方案只会检查实现类型是否实现了给定的接口。虽然TypeFilter是一种完全不同的方法,但它是从框架的初始版本返回的,它的实现会枚举所有接口,应用过滤条件并将它们存储回数组,因此从性能角度来看,这应该类似于我的笨拙解决方案。
public class Sample : ISample
{
    public void Do()
    {
        // this is a public method
    }

    void ISample.Do()
    {
        // this is the interface implementation
    }
}