Domanda

Data un'istanza di System.Reflection.Assembly.

È stato utile?

Soluzione

Non possibile.Niente specifica uno spazio dei nomi "Root".Lo spazio dei nomi predefinito nelle opzioni è una cosa di Visual Studio, non una cosa di .net

Altri suggerimenti

Mi sono imbattuto in questo dilemma molte volte quando voglio caricare una risorsa dall'assembly corrente tramite il suo flusso di risorse manifest.

Il fatto è che se incorpori un file come risorsa nell'assembly utilizzando Visual Studio, il nome della risorsa manifest verrà derivato dallo spazio dei nomi predefinito dell'assembly come definito nel progetto Visual Studio.

La migliore soluzione che ho trovato (per evitare di codificare lo spazio dei nomi predefinito come una stringa da qualche parte) è semplicemente garantire che il codice di caricamento delle risorse avvenga SEMPRE dall'interno di una classe che si trova anche nello spazio dei nomi predefinito e quindi il seguente approccio quasi generico può essere usato.

Questo esempio sta caricando uno schema incorporato.

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

Guarda anche: Come ottenere lo spazio dei nomi di un assembly?

Modificare:Ho notato anche una risposta molto dettagliata alla domanda a cui sto rispondendo http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/3a469f5d-8f55-4b25-ac25-4778f260bb7e

Un'altra modifica nel caso in cui persone con la stessa domanda vengano a cercare:Ottima idea per risolvere la domanda sul caricamento delle risorse qui: Come ottenere lo spazio dei nomi predefinito del progetto csproj (VS 2008)

Potrebbe esserci un numero qualsiasi di spazi dei nomi in un dato assembly e nulla richiede che inizino tutti da una radice comune.La cosa migliore che potresti fare sarebbe riflettere su tutti i tipi in un assembly e creare un elenco di spazi dei nomi univoci in esso contenuti.

Gli assembly non hanno necessariamente uno spazio dei nomi root.Gli spazi dei nomi e gli assembly sono ortogonali.

Quello che potresti cercare invece è trovare un tipo all'interno di quell'assembly e quindi scoprire qual è il suo spazio dei nomi.

Dovresti essere in grado di ottenere questo risultato utilizzando il membro GetExportedTypes() e quindi la proprietà Namespace da uno degli handle di tipo restituiti.

Anche in questo caso, però, non vi è alcuna garanzia che tutti i tipi siano nello stesso spazio dei nomi (o anche nella stessa gerarchia dello spazio dei nomi).

Ho appena creato una classe interna vuota chiamata Root e l'ho inserita nella root del progetto (supponendo che questo sia lo spazio dei nomi root).Quindi lo utilizzo ovunque ho bisogno dello spazio dei nomi root:

typeof(Root).Namespace;

Certo, mi ritrovo con un file inutilizzato, ma è pulito.

GetType(frm).Namespace

frm è il modulo di avvio

Ottieni tipi ti dà un elenco di Tipo oggetti definiti nell'assieme.Quell'oggetto ha una proprietà namespace.Ricorda che un assembly può avere più spazi dei nomi.

Gli spazi dei nomi non hanno nulla a che fare con gli assembly: qualsiasi mappatura tra uno spazio dei nomi e le classi in un assembly è puramente dovuta a una convenzione di denominazione (o coincidenza).

In realtà esiste un modo indiretto per ottenerlo, enumerando i nomi delle risorse manifest dell'assembly.Il nome che desideri termina con la parte che conosci.

Invece di ripetere il codice qui, vedere ottenere il nome dello spazio dei nomi predefinito per il metodo Assembly.GetManifestResourceStream()

Io uso typeof(App).Namespace nella mia applicazione WPF.La classe dell'app è obbligatoria per qualsiasi applicazione WPF e si trova nella radice.

La domanda che avevo e che mi ha portato qui era: "Se chiamo in profondità i metodi del codice della libreria N e desidero lo spazio dei nomi del progetto, ad esempio l'app MVC che è effettivamente in esecuzione, come posso ottenerlo?"

Un po' complicato ma puoi semplicemente prendere uno stacktrace e filtrare:

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

Tutto ciò che sta facendo è ottenere lo stacktrace, eseguire i metodi da quelli chiamati più recentemente a root e filtrare per System.Una volta trovata una chiamata di sistema, sa che è andata troppo oltre e ti restituisce lo spazio dei nomi immediatamente sopra di essa.Sia che tu stia eseguendo uno Unit Test, un'app MVC o un servizio, il contenitore di sistema si troverà a 1 livello più in profondità rispetto allo spazio dei nomi root del tuo progetto, quindi voilà.

In alcuni scenari in cui il codice di sistema è un intermediario (come System.Task) lungo la traccia, verrà restituita la risposta sbagliata.Il mio obiettivo era prendere ad esempio del codice di avvio e consentirgli di trovare facilmente una classe o un controller o qualsiasi altra cosa nello spazio dei nomi root, anche se il codice che esegue il lavoro si trova in una libreria.Questo realizza quel compito.

Sono sicuro che può essere migliorato: sono sicuro che questo modo complicato di fare le cose può essere migliorato in molti modi e i miglioramenti sono benvenuti.

In aggiunta a tutte le altre risposte qui, si spera senza ripetere le informazioni, ecco come ho risolto questo problema utilizzando Linq.La mia situazione è simile alla risposta di Lisa.

La mia soluzione viene fornita con i seguenti avvertimenti:

  • Stai utilizzando Visual Studio e hai uno spazio dei nomi root definito per il tuo progetto, che presumo sia quello che stai chiedendo poiché usi il termine "spazio dei nomi root"
  • Non stai incorporando tipi di interoperabilità da assembly a cui si fa riferimento
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
        )
)

Ecco un modo piuttosto semplice per ottenere lo spazio dei nomi root per un progetto di sito 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

Questo controlla semplicemente tutti gli assembly caricati per il tipo "MyProject" e restituisce lo spazio dei nomi root per quel tipo.Ciò è utile per la registrazione quando si hanno più progetti Web in un'unica soluzione che condivide un sistema di registro.Spero che questo aiuti qualcuno.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top