Project to do when at the airport: .NET assembly diff tool. Read two folders of assemblies, report what's different. Should take a few hours and be very useful from the start - surprisingly there's no free tool to do that. I need to know what's really different (e.g. which methods have different code) and I'm not interested in a differing build timestamp or GUID.
У меня выдались свободных полчаса и тулзу я сделал.
На c# c Linq оно решается в один метод.
Code Snippet
- public static IEnumerable<DiffRecord> CecilAssebmlyDiff(AssemblyDefinition firstAssembly, AssemblyDefinition secondAssembly)
- {
- var firstData = from module in firstAssembly.Modules
- from type in module.GetTypes()
- from method in type.Methods
- let parameters = method.Parameters
- let returnType = method.ReturnType
- // for some system methods body can be null, so we should check it
- where method.HasBody
- let instructions = method.Body.Instructions
- let code = method.SourceCode()
- let bytes = code
- select new { type, method, parameters, returnType, bytes };
- var secondData = from module in secondAssembly.Modules
- from type in module.GetTypes()
- from method in type.Methods
- let parameters = method.Parameters
- let returnType = method.ReturnType
- // for some system methods body can be null, so we should check it
- where method.HasBody
- let instructions = method.Body.Instructions
- let code = method.SourceCode()
- let bytes = code
- select new { type, method, parameters, returnType, bytes };
- var changedMethods = from firstMethod in firstData
- from secondMethod in secondData
- where
- // type names are the same
- firstMethod.type.FullName.Equals(secondMethod.type.FullName)
- // method names are the same
- && firstMethod.method.Name == secondMethod.method.Name
- // return typse are the same
- && firstMethod.returnType.FullName == secondMethod.returnType.FullName
- // parameters are the same
- && firstMethod.parameters.Except(secondMethod.parameters, x => x.ParameterType.FullName).Count() == 0
- //!!! dirty hack, byte arrays compared by their string representations
- // bodies ARE NOT the same
- && !firstMethod.bytes.Equals(secondMethod.bytes)
- select new { firstMethod = firstMethod, secondMethod = secondMethod };
Собственно, ничего военного. Можно было бы вынести загрузку данных для различных сборок в отдельный метод, но лениво.
Результат работы выглядит следующим образом:
$ asmdiff first second
CoolLibrary.dllCoolLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullInt32 Test.Sample(x:String)
private int Sample(string x){return 66;}
CoolLibrary.dllCoolLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=nullInt32 Test.Sample(x:String)
private int Sample(string x){return 33;}
Скачать сорцы и примеры можно здесь : проект на гитхабе
использовать просто "asmdiff folder1 folder2"
Зы. Рекурсивного обхода директорий нет.
ЗЫЫ. Обработки исключений тоже пока никакой.
Немає коментарів:
Дописати коментар