我正在使用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"
}
}
一个尴尬的解决方案:
var interfaces = from i in input.MethodBase.DeclaringType.GetInterfaces()
where i.GetCustomAttributes(typeof(CustomAttribute), true).Length > 0
where i.GetMethod(input.MethodBase.Name, input.MethodBase.GetParameters().Select(p=>p.ParameterType).ToArray()) != null
select i;
答案 0 :(得分:0)
我能提出的唯一解决办法(尽管你的解决方案不是那么尴尬)。
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;
}
答案 1 :(得分: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;
答案 2 :(得分:0)
我认为你坚持枚举接口;我还没有看到访问特定界面的方法。
此外,如果明确实现接口,则可能会出现一个小边缘情况。在这种情况下(void ISample.Do()
),MethodBase.Name将是完全限定的方法名称(例如MyApp.ISample.Do
),而不是Do
。
我发现的唯一解决方案是剥离主要信息。 E.g。
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 ISample.Do()
将IsFinal,IsVirtual,IsPrivate,IsHideBySig设置为true。但我不确定这对所有情况都是足够的。