Есть ли способ получить все пространства имен, которые вы «используете» внутри класса через код C #? - PullRequest
12 голосов
/ 28 апреля 2011

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

Например,

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.Text "," System.Reflection "и т. Д.

РЕДАКТИРОВАТЬ: Как указано ниже, я использую это http://kamimucode.com/Home.aspx/C-sharp-Eval/1 - C #оценщик, и я должен кормить TypeParser списком пространств имен.Дело в том, что я не всегда буду знать, какие поставить.Я работаю над простым языком сценариев в C #, и с его помощью я смогу также вызывать код C #.Другой вариант - создать ключевое слово типа «using» на языке сценариев, но я действительно не хочу этого делать.Я хочу иметь возможность выбирать объект C #, делать с ним все, что захочу, через мой script.txt и свободно использовать его пространства имен, на которые есть ссылки.

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

Ответы [ 3 ]

5 голосов
/ 29 апреля 2011

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

Так что, если у вас есть один КЛАСС на файл, это будет работать: если вы что-то упустили (я ищу поля и методы, возможно, что-тоне принимается во внимание, если это так, просто добавьте)

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
1 голос
/ 29 апреля 2011

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

1 голос
/ 28 апреля 2011

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

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 может быть неправильным, чтобы обрезать точку с запятой на конце. Вы должны будете проверить это, чтобы узнать, что это должно быть. Кроме того, это предполагает, что ваш код отформатирован довольно стандартным способом. Если это не так, это не сработает.

...