给定一个DLL文件,我希望能够找到该DLL文件中的方法的所有调用。我怎样才能做到这一点?C#反射和查找所有引用
从本质上讲,我怎样才能以编程方式做Visual Studio已经做了什么?
我不想使用像.NET Reflector这样的工具来做到这一点,但反射很好,可能是必要的。
给定一个DLL文件,我希望能够找到该DLL文件中的方法的所有调用。我怎样才能做到这一点?C#反射和查找所有引用
从本质上讲,我怎样才能以编程方式做Visual Studio已经做了什么?
我不想使用像.NET Reflector这样的工具来做到这一点,但反射很好,可能是必要的。
要找出使用方法MyClass.Foo()
的位置,必须分析所有包含MyClass
的程序集引用的所有程序集的类。我写了一个关于这个代码的外观的简单证明。在我的例子中,我使用this library写的JB Evain(这只是a single .cs file):
我写了一个小测试类来分析:
public class TestClass
{
public void Test()
{
Console.WriteLine("Test");
Console.Write(10);
DateTime date = DateTime.Now;
Console.WriteLine(date);
}
}
而且我写了这个代码打印出内TestClass.Test()
使用的所有方法:
MethodBase methodBase = typeof(TestClass).GetMethod("Test");
var instructions = MethodBodyReader.GetInstructions(methodBase);
foreach (Instruction instruction in instructions)
{
MethodInfo methodInfo = instruction.Operand as MethodInfo;
if(methodInfo != null)
{
Type type = methodInfo.DeclaringType;
ParameterInfo[] parameters = methodInfo.GetParameters();
Console.WriteLine("{0}.{1}({2});",
type.FullName,
methodInfo.Name,
String.Join(", ", parameters.Select(p => p.ParameterType.FullName + " " + p.Name).ToArray())
);
}
}
它给了我下面的输出:
System.Console.WriteLine(System.String value);
System.Console.Write(System.Int32 value);
System.DateTime.get_Now();
System.Console.WriteLine(System.Object value);
这个例子显然远未完成,因为它没有处理ref和out参数,也没有处理泛型参数。我相信,也忘记了其他细节。它只是表明它可以完成。
不错。这也使用Linq作为select语句。有时间构建一些依赖关系图。 – user420667 2011-03-30 20:47:41
我收到此错误消息:“价值不符合预期范围。”从这段代码:'this.body = method.GetMethodBody();如果(this.body == null)抛出新的ArgumentException();'我想知道如何有无身体的方法(或者还有什么可以进行)。有什么想法吗? – ekkis 2013-09-14 00:22:39
@ekkis:(抽象类的)抽象方法是没有身材的。您可以通过检查“MethodBase.IsAbstract”来检查方法是否抽象。 – 2013-09-14 01:00:23
请参阅堆栈溢出问题Get a list of functions for a DLL。
从上面的(感谢乔恩斯基特)受骗:
对于特定的组件,您可以使用Assembly.GetTypes拿到类型,然后为每个呼叫类型Type.GetMethods(),Type.GetProperties ()等,或者只是Type.GetMembers()。
但是,对于插件功能来说,拥有插件必须实现的通用接口通常是一个好主意 - 这可以减少您需要使用的反射量。使用Type.IsAssignableFrom()检查某个类型是否与特定接口兼容。
您可能还想看看托管扩展性框架,它可以使实现扩展系统更容易。
我不明白这个答案如何帮助找到给定方法的调用。它有助于列出目标程序集中的类型,方法,属性等,但OP正在寻找一种方法来检测给定方法是否调用另一个方法。 – 2011-03-30 17:51:10
这不是OP询问的问题。 – 2011-03-30 17:52:38
这不是OP正在寻找的东西。这列出了方法,但没有列出它们的调用。 – jason 2011-03-30 17:52:41
我会考虑反映Visual Studio程序集,看看你是否可以在逆向工程代码库中找到它。我相信VS实际上是在浏览代码而不是反思。正如Michael所发布的,反射对于确定组件的位数非常重要,但不是那些位的消费者。但是,我没有重新审视反思来确认我的怀疑。
您可以查看MSDN杂志文章Determining .NET Assembly and Method References。
+1:请注意,你将不得不搜索一些IL阅读器 - 反射器的一个不是直接可用,据我所知... – 2011-03-30 18:00:50
好文章。但它建议使用Reflector作为方法依赖关系。我想他们都归结为解析IL。 – user420667 2011-03-30 20:46:43
单靠反射并不足以找到给定装配中的方法的所有引用。反射为任何特定方法的主体提供了一个字节数组(MethodInfo.GetMethodBody.GetILAsByteArray),您必须自己解析它以引用其他方法。有几个公开可用的“CIL阅读器”库(我没有使用它们 - 希望有人会发布更多)。
添加FxCop选项 - 根据您的场景,您可以重复使用由FxCop(Visual Studio代码分析)提供的CIL分析逻辑,并添加自定义规则(如果作为代码分析的一部分运行它)对您而言可以。
您是否需要检测对该方法的静态调用?应该用反射和反射发射来检测电话吗? – 2011-03-30 17:48:02
而且应该使用非托管代码吗?并非所有的DLL都支持反射。 – 2011-03-30 17:50:24
@Darin:那些会锦上添花,但没有必要。 @James:我不认为我必须担心非托管代码。我怎么能在不支持反射的dll上做到这一点? – user420667 2011-03-30 18:18:34