Получить все пространства имен, связанные с типом? - PullRequest
2 голосов
/ 12 июля 2020

Есть ли способ получить все пространства имен, связанные с классом / типом, с помощью Reflection?

Например, если моя переменная:

var list = List<MyClass> 

и мой класс определен как

public class MyClass
{
   property int32 MyNumber {get; set;}
}

Я хотел бы иметь возможность получить следующие возвращенные пространства имен:

  • MyCompany.MyClass (поскольку он используется моим MyClass)
  • System. Collections.Generi c (поскольку он используется List)
  • System as int32 (поскольку он используется MyNumber)

Спасибо.

1 Ответ

0 голосов
/ 12 июля 2020

Вы можете проанализировать тип с помощью отражения.

Вы получите намного больше результатов, чем ожидалось, из-за дизайна фреймворка.

Надеюсь, я не сделал слишком много ошибок.

Тест

namespace ConsoleApp
{
  public class Program
  {
    static public void Main(string[] args)
    {
      var list = new List<MyClass>();
      var typeSearched = list.GetType();
      Console.WriteLine($"{typeSearched.Name} needs these namespaces:");
      foreach ( var item in typeSearched.GetUsingNamespaces().OrderBy(kvp => kvp.Key) )
      {
        string names = string.Join(Environment.NewLine + "    ",
                                   item.Value.Select(t => t.Name)
                                             .OrderBy(n => n));
        Console.WriteLine($"# {item.Key} for type(s):" + Environment.NewLine +
                          $"    {names}");
        Console.WriteLine();
    }
  }
  public class MyClass
  {
    public Int32 MyNumber {get; set;}
  }
}

Вспомогательный класс рефлексии

using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;

namespace ConsoleApp
{
  static public class ReflexionHelper
  {
    // See below
  }
}

Инструменты методы

static public void AddNoDuplicates<T>(this IList<T> list, T value)
{
  if ( !list.Contains(value) ) list.Add(value);
}

static public void AddNoDuplicates<TKey, TValue>(this IDictionary<TKey, List<TValue>> list,
                                                 TKey key, TValue value)
{
  if ( key == null ) return;
  if ( !list.ContainsKey(key) )
    list.Add(key, new List<TValue>() { value });
  else
  if ( !list[key].Contains(value) )
    list[key].Add(value);
}

static public void AddRangeNoDuplicates<T>(this IList<T> list, IEnumerable<T> collection)
{
  foreach ( T value in collection )
    if ( !list.Contains(value) )
      list.Add(value);
}

Метод синтаксического анализа типа

static public Dictionary<string, List<Type>> GetUsingNamespaces(this Type typeSearched)
{
  var result = new Dictionary<string, List<Type>>();
  result.AddNoDuplicates(typeSearched.Namespace, typeSearched);
  foreach ( Type type in typeSearched.GetMembersTypes() )
  {
    result.AddNoDuplicates(type.Namespace, type);
    foreach ( var implement in type.GetInterfaces() )
      result.AddNoDuplicates(implement.Namespace, implement);
    foreach ( var argument in type.GetGenericArguments() )
      result.AddNoDuplicates(argument.Namespace, argument);
  }
  return result;
}

Метод получения всех членов типа

static public List<Type> GetMembersTypes(this Type type)
{
  var flags = BindingFlags.Static
            | BindingFlags.Instance
            | BindingFlags.Public
            | BindingFlags.NonPublic;
  var result = new List<Type>();
  foreach ( var field in type.GetFields(flags) )
    result.AddNoDuplicates(field.FieldType);
  foreach ( var property in type.GetProperties(flags) )
    result.AddNoDuplicates(property.PropertyType);
  foreach ( var ev in type.GetEvents(flags) )
    result.AddNoDuplicates(ev.EventHandlerType);
  foreach ( var method in type.GetMethods(flags) )
  {
    result.AddNoDuplicates(method.ReturnType);
    foreach ( var a in method.GetParameters() )
      result.AddNoDuplicates(a.ParameterType);
  }
  foreach ( var constructor in type.GetConstructors() )
    foreach ( var param in constructor.GetParameters() )
      result.AddNoDuplicates(param.ParameterType);
  foreach ( var nested in type.GetNestedTypes(flags) )
    result.AddRangeNoDuplicates(GetMembersTypes(nested));
  return result;
}

Будущие улучшения

Анализ атрибутов и других забытых вещей.

Короткий тестовый вывод

ConsoleApp
System
System.Collections
System.Collections.Generic
System.Collections.ObjectModel
System.Reflection
System.Runtime.InteropServices
System.Runtime.Serialization

Тестовый вывод заполнен

# ConsoleApp for type(s):
    MyClass
    MyClass[]

# System for type(s):
    Action`1
    Array
    Boolean
    Comparison`1
    Converter`2
    ICloneable
    IComparable
    IComparable`1
    IComparable`1
    IComparable`1
    IConvertible
    IDisposable
    IEquatable`1
    IEquatable`1
    IEquatable`1
    IFormattable
    Int32
    Object
    Predicate`1
    String
    Type
    Void

# System.Collections for type(s):
    ICollection
    IEnumerable
    IEnumerator
    IList
    IStructuralComparable
    IStructuralEquatable

# System.Collections.Generic for type(s):
    Enumerator
    ICollection`1
    ICollection`1
    ICollection`1
    ICollection`1
    IComparer`1
    IEnumerable`1
    IEnumerable`1
    IEnumerable`1
    IEnumerable`1
    IEnumerable`1
    IEnumerator`1
    IEnumerator`1
    IList`1
    IList`1
    IList`1
    IList`1
    IReadOnlyCollection`1
    IReadOnlyCollection`1
    IReadOnlyCollection`1
    IReadOnlyCollection`1
    IReadOnlyList`1
    IReadOnlyList`1
    IReadOnlyList`1
    IReadOnlyList`1
    List`1
    List`1
    List`1
    List`1
    T
    T
    T[]
    TOutput

# System.Collections.ObjectModel for type(s):
    ReadOnlyCollection`1

# System.Reflection for type(s):
    ICustomAttributeProvider
    IReflect

# System.Runtime.InteropServices for type(s):
    _MemberInfo
    _Type

# System.Runtime.Serialization for type(s):
    ISerializable

Некоторые имена типов дублируются, но экземпляр Type отличается ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...