Есть ли способ получить все пространства имен, которые вы используете в классе через код С#?

Есть ли способ получить List<string>, который содержит все "usings" в пространстве имен/классе?

Например

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Linq.Dynamic;
using System.Text.RegularExpressions;
using System.Reflection;
namespace MyNamespace.Other.Scripting
{

У меня был бы список с "System", "System.Text", "System.Reflection" и т.д.

EDIT: Как указано ниже, Я использую этот http://kamimucode.com/Home.aspx/C-sharp-Eval/1 - оценщик С#, и мне нужно передать TypeParser список пространств имен. Дело в том, что я не всегда буду знать, какие из них поставить. Я работаю над простым языком сценариев на С#, и из этого я также смогу позвонить на С#. Другой альтернативой является создание ключевого слова, такого как "использование" на языке сценариев, но я действительно не хочу этого делать. Я хочу, чтобы иметь возможность выбрать объект С#, делать все, что я хочу, с помощью моего script.txt, и иметь возможность использовать свои ссылочные пространства имен.

Я хочу использовать его в своем движке Xna Game, чтобы писать собственные скрипты, которые могут выполнять С# вместе с моими простыми функциями script.

Ответ 1

Это будет работать для всех типов в методах объявляющего класса, однако он не даст всех пространств имен для всех классов в файле, где он был до компиляции. Это невозможно, потому что после компиляции фреймворк не может знать, что было в файлах.

Итак, если у вас есть один класс для каждого файла, это будет работать: Если вам что-то не хватает (я ищу поля и методы, возможно, что-то не учитывается в учетной записи, если это так просто добавить)

List<string> namespaces = new List<string>();

        var m = MethodInfo.GetCurrentMethod();

            foreach (var mb in m.DeclaringType.GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic))
            {
                if (mb.MemberType == MemberTypes.Method && ((MethodBase)mb).GetMethodBody() != null)
                {

                    foreach (var p in ((MethodInfo)mb).GetMethodBody().LocalVariables)
                    {
                        if (!namespaces.Contains(p.LocalType.Namespace))
                        {
                            namespaces.Add(p.LocalType.Namespace);
                            Console.WriteLine(p.LocalType.Namespace);
                        }
                    }
                }
                else if (mb.MemberType == MemberTypes.Field) {
                    string ns = ((System.Reflection.FieldInfo)mb).FieldType.Namespace;
                    if (!namespaces.Contains(ns))
                    {                        
                        namespaces.Add(ns);
                        Console.WriteLine(ns);
                    }
                }
            }

Пример вывода для моего случая:

System
System.Collections.Generic
System.Reflection
WindowsFormsApplication2
System.Linq.Expressions

Ответ 2

Здесь грубая непроверенная попытка начать работу:

IEnumerable<string> GetNamespacesUsed(string fileName)
{
    var lines = System.IO.File.ReadAllLines(fileName);
    var usingLines = lines.Where(
        x => x.StartsWith("using ") && !x.StartsWith("using ("));

    foreach (var line in usingLines)
    {
        if (line.Contains("="))
            yield return line.Substring(line.IndexOf("="), line.Length - 1);
        else
            yield return line.Substring(line.Length - 1);
    }
}

line.Length - 1 может быть неверно отрезать точку с запятой на конце. Вам нужно будет проверить его, чтобы узнать, что это должно быть. Кроме того, это предполагает, что ваш код отформатирован довольно стандартным образом. Если это не так, это не сработает.

Ответ 3

Вы можете использовать Mono Cecil, чтобы прочитать определение класса из сборки и получить список всех ссылочных типов в каждом методе. Оттуда вы можете извлечь список пространств имен (полное имя типа за вычетом последней части).