Pregunta

Dada una instancia de System.Reflection.Assembly.

¿Fue útil?

Solución

Imposible.Nada especifica un espacio de nombres "raíz".El espacio de nombres predeterminado en las opciones es una cuestión de Visual Studio, no de .net.

Otros consejos

Me he encontrado con este dilema muchas veces cuando quiero cargar un recurso del ensamblado actual mediante su flujo de recursos manifiesto.

El hecho es que si incrusta un archivo como recurso en su ensamblado usando Visual Studio, su nombre de recurso manifiesto se derivará del espacio de nombres predeterminado del ensamblado tal como se define en el proyecto de Visual Studio.

La mejor solución que se me ocurrió (para evitar codificar el espacio de nombres predeterminado como una cadena en algún lugar) es simplemente garantizar que el código de carga de recursos SIEMPRE ocurra desde dentro de una clase que también esté en el espacio de nombres predeterminado y luego el siguiente enfoque casi genérico. puede ser usado.

Este ejemplo está cargando un esquema incrustado.

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);

Ver también: ¿Cómo obtener el espacio de nombres de una asamblea?

Editar:También noté una respuesta muy detallada a la pregunta que estoy respondiendo en http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/3a469f5d-8f55-4b25-ac25-4778f260bb7e

Otra edición en caso de que personas con la misma pregunta vengan a buscar:Excelente idea para resolver la cuestión de la carga de recursos aquí: ¿Cómo obtener el espacio de nombres predeterminado del proyecto csproj (VS 2008)?

Puede haber cualquier número de espacios de nombres en un conjunto determinado y nada requiere que todos comiencen desde una raíz común.Lo mejor que podría hacer sería reflexionar sobre todos los tipos en un ensamblaje y crear una lista de espacios de nombres únicos contenidos en él.

Los ensamblados no necesariamente tienen un espacio de nombres raíz.Los espacios de nombres y los ensamblajes son ortogonales.

En su lugar, lo que puede estar buscando es encontrar un tipo dentro de ese ensamblaje y luego descubrir cuál es su espacio de nombres.

Debería poder lograr esto usando el miembro GetExportedTypes() y luego usando la propiedad Namespace de uno de los identificadores de tipo devueltos.

Sin embargo, nuevamente, no hay garantía de que todos los tipos estén en el mismo espacio de nombres (o incluso en la misma jerarquía de espacios de nombres).

Acabo de crear una clase interna vacía llamada Root y la puse en la raíz del proyecto (suponiendo que este sea su espacio de nombres raíz).Luego uso esto en todos los lugares donde necesito el espacio de nombres raíz:

typeof(Root).Namespace;

Seguro que termino con un archivo sin usar, pero está limpio.

GetType(frm).Namespace

frm es el formulario de inicio

Obtener tipos te da una lista de Tipo objetos definidos en el ensamblaje.Ese objeto tiene una propiedad de espacio de nombres.Recuerde que un ensamblaje puede tener múltiples espacios de nombres.

Los espacios de nombres no tienen nada que ver con los ensamblados: cualquier mapeo entre un espacio de nombres y las clases en un ensamblado se debe puramente a una convención de nomenclatura (o coincidencia).

En realidad, existe una forma indirecta de obtenerlo, enumerando los nombres de los recursos manifiestos del ensamblado.El nombre que deseas termina con la parte que conoces.

En lugar de repetir el código aquí, consulte obtener el nombre del espacio de nombres predeterminado para el método Assembly.GetManifestResourceStream()

yo suelo typeof(App).Namespace en mi aplicación WPF.La clase de aplicación es obligatoria para cualquier aplicación WPF y está ubicada en la raíz.

La pregunta que tuve y que me llevó aquí fue: "Si llamo a N métodos de código de biblioteca en profundidad y quiero el espacio de nombres del Proyecto, por ejemplo, la aplicación MVC que realmente se está ejecutando, ¿cómo lo obtengo?"

Un poco complicado, pero puedes tomar un seguimiento de pila y filtrar:

    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;
    }

Todo lo que esto hace es obtener el seguimiento de la pila, ejecutar los métodos desde los llamados más recientemente a la raíz y filtrar por System.Una vez que encuentra una llamada al sistema, sabe que ha ido demasiado lejos y le devuelve el espacio de nombres inmediatamente encima.Ya sea que esté ejecutando una prueba unitaria, una aplicación MVC o un servicio, el contenedor del sistema estará ubicado un nivel más profundo que el espacio de nombres raíz de su proyecto, así que listo.

En algunos escenarios donde el código del sistema es un intermediario (como System.Task) a lo largo del seguimiento, esto devolverá una respuesta incorrecta.Mi objetivo era tomar, por ejemplo, algún código de inicio y permitirle encontrar fácilmente una clase o controlador o lo que sea en el espacio de nombres raíz, incluso si el código que realiza el trabajo se encuentra en una biblioteca.Esto logra esa tarea.

Estoy seguro de que se puede mejorar. Estoy seguro de que esta forma ingeniosa de hacer las cosas se puede mejorar de muchas maneras y las mejoras son bienvenidas.

Agregando a todas las demás respuestas aquí, con suerte sin repetir información, así es como resolví esto usando Linq.Mi situación es similar a la respuesta de Lisa.

Mi solución viene con las siguientes advertencias:

  • Estás usando Visual Studio y tienes un espacio de nombres raíz definido para tu proyecto, que supongo que es lo que estás pidiendo ya que usas el término "espacio de nombres raíz".
  • No estás incrustando tipos de interoperabilidad de ensamblados a los que se hace referencia
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
        )
)

A continuación se muestra una forma bastante sencilla de obtener el espacio de nombres raíz para un proyecto de sitio web.

''' <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

Esto simplemente verifica todos los ensamblados cargados para el tipo "MiProyecto" y devuelve el espacio de nombres raíz para ese tipo.Esto es útil para iniciar sesión cuando tiene varios proyectos web en una única solución que comparte un sistema de registro.Espero que esto ayude a alguien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top