鉴于DLL文件,我希望能够找到该DLL文件中所有方法的调用。我怎么能这样做?
基本上,我如何以编程方式执行Visual Studio已经执行的操作?
我不想使用像.NET Reflector之类的工具来做这件事,但反思很好,可能也是必要的。
答案 0 :(得分:48)
要找出使用方法MyClass.Foo()
的位置,您必须分析所有包含对包含MyClass
的程序集的引用的程序集的所有类。我写了一个关于代码如何看起来的简单概念证明。在我的例子中,我使用了由Jb Evain编写的this library(它只是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参数,并且它不处理泛型参数。我确信忘记了其他细节。它只是表明它可以完成。
答案 1 :(得分:3)
单独的反射不足以找到给定程序集中对方法的所有引用。 Reflection为您提供了任何特定方法(MethodInfo.GetMethodBody.GetILAsByteArray)的主体的字节数组,您必须自己解析它以获取对其他方法的引用。有几个公开的“CIL读者”图书馆(我没有使用它们 - 希望有人会发布更多内容)。
添加FxCop选项 - 根据您的场景,您可以重用FxCop提供的CIL解析逻辑(Visual Studio代码分析)并添加您的自定义规则,如果在代码分析中运行它是可以的你。
答案 2 :(得分:2)
您可以查看MSDN杂志文章 Determining .NET Assembly and Method References 。
答案 3 :(得分:1)
我会考虑反映Visual Studio程序集,看看你是否可以在逆向工程代码库中找到它。我相信VS实际上是在导航代码而不是反映。正如迈克尔发布的那样,反思非常适合确定装配的位,而不是那些位的消费者。然而,我没有重新审视反思来证实我的怀疑。
答案 4 :(得分:0)
嘿,这是一个示例,假设您要搜索当前程序集中的所有调用。我编写了这个尝试获取参数值,以便为具有一些默认值的方法设置一些约束。但是我无法获得参数值,我只获得了类型和默认值。
var currentAssembly = Assembly.GetExecutingAssembly();
foreach (var method in currentAssembly.GetTypes().Where(type => type.IsClass)
.SelectMany(cl => cl.GetMethods())
.OfType<MethodBase>()
.SelectMany(mb => mb.GetInstructions())
.Select(inst => inst.Operand).OfType<MethodInfo>()
.Where(mi => mi.Name == "<YourMethodName>"))
{
//here are your calls.
}
希望它有所帮助。
答案 5 :(得分:-1)
请参阅Stack Overflow问题 Get a list of functions for a DLL 。
从上面撕掉(感谢Jon Skeet):
对于特定的程序集,可以使用Assembly.GetTypes来获取类型,然后为每个类型调用Type.GetMethods(),Type.GetProperties()等,或者只使用Type.GetMembers()。
但是,对于插件功能,通常最好有一个插件必须实现的通用接口 - 这样可以减少需要使用的反射量。使用Type.IsAssignableFrom()检查类型是否与特定接口兼容。
您可能还想查看Managed Extensibility Framework,它可以更轻松地实现扩展系统。