2010-01-06 1 views
0

Я работал над API, который инкапсулирует другой, более сложный в использовании API. Цель заключается в том, что мой API не требует от пользователя касаться какого-либо старого API: 1) не требует каких-либо параметров классов в старом API и 2) не возвращает никаких экземпляров классов в старом API. Есть ли программа, возможно, плагин Visual Studio, который может анализировать мое решение C# и предоставить мне список всех типов возвращаемых данных из общедоступных методов в общедоступных классах, а также всех типов параметров в таких методах? В противном случае мне кажется, что мне придется вручную пройти через все мои классы и посмотреть, открыт ли какой-либо из старого API для пользователя.отражение типов возвращаемых списков, параметров в приложении C# из определенного пространства имен

Редактирование: Поскольку я использовал MSTest для модульного тестирования моего API в любом случае, я добавил еще один модульный тест для использования отражения и Fail, если были открыты какие-либо части старого API. Тем не менее, я застрял с проблемой отражения. У меня есть using OldAPI в единичном тестовом классе, а затем я использую

AppDomain.CurrentDomain.GetAssemblies().SelectMany(
    assembly => assembly.GetTypes() 
) 

, чтобы получить список типов во всех сборках загруженных в данный момент. Затем я перебираю их в надежде разобрать список типов только в пространстве имен OldAPI. Проблема в том, что пространство имен OldAPI не отображается. Я вижу пространства имен, такие как Microsoft.VisualStudio.TestTools, System.Reflection и другие, которые включены в операторы using в тестовом классе, но нет «OldAPI». Может ли это быть из-за COM-материала со старым API, поэтому AppDomain.CurrentDomain.GetAssemblies() не включает сборку, хотя она включена через оператор using в классе?

Решение: я получил необходимую сборку, произвольно выбирая один класс я знаю, в OldAPI и делать следующее, благодаря SLaks 'комментарий:

Func<Type, bool> isBad = t => t.Assembly == typeof(OldAPI.SomeClass).Assembly; 

Вот фрагмент моего модульного тестирования для проверки если какие-либо из классов моего API: использовать любого из OldAPI «классов s, благодаря SLaks» ответа:

MethodInfo[] badMethods = methods.Where(
    m => (
      isBad(m.ReturnType) || 
      m.GetParameters().Any(p => isBad(p.ParameterType)) 
     ) && !isBad(m.DeclaringType) 
).ToArray(); 
string[] badMethodNames = badMethods.Select(
    m => m.DeclaringType.Name + "." + m.Name 
).Distinct().ToArray(); 
Assert.AreEqual(0, badMethodNames.Length, "Some methods in " + 
    monitoredNamespaces + " projects expose OldAPI: " + 
    string.Join(", ", badMethodNames)); 
+1

Вы вводите в заблуждение сборки с пространствами имен. Вы можете собрать старый API, написав 'typeof (OldType).Assembly'. – SLaks

ответ

1

Вы можете использовать LINQ, как это:

Func<Type, bool> isBad = t => t.Assembly == badAssembly; 

var types = yourAssembly.GetTypes(); 
var methods = types.SelectMany(t => t.GetMethods()).ToArray(); 

var badMethods = methods.Where(m => isBad(m.ReturnType) 
    || m.GetParameters().Any(p => isBad(p.ParameterType); 

var properties = types.SelectMany(t => t.GetProperties()).ToArray(); 
var badProperties = properties.Where(p => isBad(p.PropertyType)); 

Это было бы проще всего сделать в LINQPad.

Обратите внимание, что это не распространяется на общие типы, поэтому оно игнорирует List<BadType>.
Вы должны, вероятно, сделать isBad рекурсивным. (В этом случае вы должны включить его в обычную функцию)

+0

У вас есть пара неуместных круглых скобок: одна дополнительная в конце 'var methods' и одна отсутствует в конце' var badMethods'. –

+0

Я изменил параметр 'badMethods' на' Where', чтобы включить '&&! IsBad (m.DeclaringType)', в противном случае я вижу, что все классы из плохого API перечислены, потому что, конечно, они используют другие классы в плохом API. Я хочу, чтобы только мои собственные классы использовали плохой API для перечисления. –

+0

Я также поместил 'ToArray()' в конец 'var badMethods' и' var badProperties', потому что 'Where' возвращает' IEnumerable'. –

1

Я не AWAR e существующего инструмента для этого, но это не значит, что вы должны сделать это вручную - вы можете легко написать свой собственный инструмент, чтобы сделать это, используя Reflection. В основном вам просто нужно выполнить итерацию по Assembly.GetExportedTypes(); для каждого типа вызовите Type.GetMethods() и Type.GetProperties() и выполните итерацию по результатам; и демпинг возвращаемых и типов параметров для каждого метода или свойства, которое является общедоступным.

Обратите внимание, что такой рукописный инструмент должен работать над вашей скомпилированной сборкой, а не с исходным кодом C#. Вы можете сделать что-то похожее на исходный код, но это зависит от модели кода Visual Studio, которая довольно сложна в использовании и, вероятно, не стоит усилий для одноразового использования!

+0

Возможно, вы дали мне идею для проекта с открытым исходным кодом, чтобы писать в свободное время. :) –