отражение в списке возвращаемых типов, параметров в приложении C # из определенного пространства имен - PullRequest
1 голос
/ 07 января 2010

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

Редактировать: Поскольку я все равно использую 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, благодаря ответу 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));

Ответы [ 2 ]

1 голос
/ 07 января 2010

Вы можете использовать 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 рекурсивным. (В этом случае вы должны превратить его в обычную функцию)

1 голос
/ 07 января 2010

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

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

...