Как вы получаете корневое пространство имен сборки?

StackOverflow https://stackoverflow.com/questions/96317

  •  01-07-2019
  •  | 
  •  

Вопрос

Приведен пример System.Reflection.Assembly.

Это было полезно?

Решение

Это невозможно.Ничто не указывает "Корневое" пространство имен.Пространство имен по умолчанию в параметрах относится к Visual Studio, а не к .net

Другие советы

Я сталкивался с этой дилеммой много раз, когда я хотел загрузить ресурс из текущей сборки с помощью потока ресурсов манифеста.

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

Лучшее решение, которое я придумал (чтобы избежать жесткого кодирования пространства имен по умолчанию в виде строки где-либо), - это просто убедиться, что код загрузки вашего ресурса ВСЕГДА происходит изнутри класса, который также находится в пространстве имен по умолчанию, и тогда может быть использован следующий почти универсальный подход.

В этом примере выполняется загрузка встроенной схемы.

XmlSchema mySchema;
string resourceName = "MyEmbeddedSchema.xsd";
string resourcesFolderName = "Serialisation";
string manifestResourceName = string.Format("{0}.{1}.{2}",
    this.GetType().Namespace, resourcesFolderName, resourceName);
using (Stream schemaStream = currentAssembly.GetManifestResourceStream(manifestResourceName))
    mySchema = XmlSchema.Read(schemaStream, errorHandler);

Смотрите также: Как получить пространство имен сборки?

Редактировать:Также заметил очень подробный ответ на вопрос, на который я отвечаю по адресу http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/3a469f5d-8f55-4b25-ac25-4778f260bb7e

Еще одна правка на случай, если люди с таким же вопросом придут искать:Отличная идея решить вопрос с загрузкой ресурсов здесь: Как получить пространство имен проекта csproj по умолчанию (VS 2008)

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

Сборки не обязательно имеют корневое пространство имен.Пространства имен и Сборки ортогональны.

Вместо этого вы, возможно, ищете тип внутри этой Сборки, а затем выясняете, каково его пространство имен.

Вы должны быть в состоянии выполнить это, используя элемент GetExportedTypes(), а затем используя свойство Namespace из одного из возвращаемых дескрипторов типа.

Опять же, однако, нет никаких гарантий, что все типы находятся в одном пространстве имен (или даже в одной иерархии пространств имен).

Я только что создал пустой внутренний класс с именем Root и поместил его в корневой каталог проекта (предполагая, что это ваше корневое пространство имен).Затем я использую это везде, где мне нужно корневое пространство имен:

typeof(Root).Namespace;

Конечно, в итоге я получаю неиспользуемый файл, но он чистый.

GetType(frm).Namespace

frm является ли форма запуска

Получение типов дает вам список Тип объекты, определенные в сборке.Этот объект имеет свойство пространства имен.Помните, что сборка может иметь несколько пространств имен.

Пространства имен не имеют ничего общего со сборками - любое сопоставление между пространством имен и классами в сборке происходит исключительно из-за соглашения об именовании (или совпадения).

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

Вместо того чтобы повторять код здесь, пожалуйста, ознакомьтесь получаем имя пространства имен по умолчанию для сборки.Метод GetManifestResourceStream()

Я использую typeof(App).Namespace в моем приложении WPF.Класс app является обязательным для любого приложения WPF и находится в корневом каталоге.

У меня возник вопрос, который привел меня сюда: "Если я вызываю библиотечный код N методами deep и хочу получить пространство имен проекта - например, приложение MVC, которое на самом деле запущено, - как мне это получить?"

Немного халтурно, но вы можете просто взять stacktrace и отфильтровать:

    public static string GetRootNamespace()
    {
        StackTrace stackTrace = new StackTrace();
        StackFrame[] stackFrames = stackTrace.GetFrames();
        string ns = null;
        foreach(var frame in stackFrames)
        {
            string _ns = frame.GetMethod().DeclaringType.Namespace;
            int indexPeriod = _ns.IndexOf('.');
            string rootNs = _ns;
            if (indexPeriod > 0)
                rootNs = _ns.Substring(0, indexPeriod);

            if (rootNs == "System")
                break;
            ns = _ns;
        }

        return ns;
    }

Все, что это делает, - это получает stacktrace, запускает методы от последнего вызова до root и фильтрует для System.Как только он находит Системный вызов, он понимает, что зашел слишком далеко, и возвращает вам пространство имен непосредственно над ним.Независимо от того, запускаете ли вы модульный тест, приложение MVC или Сервис, системный контейнер будет располагаться на 1 уровень глубже корневого пространства имен вашего проекта, так что вуаля.

В некоторых сценариях, где системный код является посредником (например, System.Task) в трассировке, это вернет неправильный ответ.Моя цель состояла в том, чтобы взять, например, некоторый код запуска и позволить ему легко найти класс, или контроллер, или что-то еще в корневом пространстве имен, даже если код, выполняющий эту работу, находится в библиотеке.Это позволяет выполнить эту задачу.

Я уверен, что это можно улучшить - я уверен, что этот хакерский способ ведения дел может быть улучшен многими способами, и улучшения приветствуются.

Добавляя ко всем остальным ответам здесь, надеюсь, без повторения информации, вот как я решил это с помощью Linq.Моя ситуация похожа на ответ Лизы.

Мое решение содержит следующие оговорки:

  • Вы используете Visual Studio, и для вашего проекта определено корневое пространство имен, которое, я полагаю, является тем, о чем вы просите, поскольку вы используете термин "корневое пространство имен".
  • Вы не встраиваете типы взаимодействия из сборок, на которые даны ссылки
Dim baseNamespace = String.Join("."c,
    Me.GetType().Assembly.ManifestModule.GetTypes().
        Select(Function(type As Type)
                    Return type.Namespace.Split("."c)
                End Function
        ).
        Aggregate(Function(seed As String(), splitNamespace As String())
                        Return seed.Intersect(splitNamespace).ToArray()
                    End Function
        )
)

Вот довольно простой способ получить корневое пространство имен для веб-проекта.

''' <summary>
''' Returns the namespace of the currently running website
''' </summary>
Public Function GetWebsiteRootNamespace() As String
    For Each Asm In AppDomain.CurrentDomain.GetAssemblies()
        If Asm Is Nothing OrElse Asm.IsDynamic Then Continue For

        For Each Typ In Asm.GetTypes
            If Typ Is Nothing OrElse Typ.Name Is Nothing Then Continue For
            If Typ.Name = "MyProject" Then Return Typ.Namespace.Split("."c)(0)
        Next
    Next

    Return Nothing
End Function

Это просто проверяет все загруженные сборки на наличие типа "MyProject" и возвращает корневое пространство имен для этого типа.Это полезно для ведения журнала, когда у вас есть несколько веб-проектов в одном решении, совместно использующих систему ведения журнала.Надеюсь, это кому-то поможет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top