2010-04-09 8 views
8

J'ai une chaîne et je veux vérifier si elle représente un espace de nom propre, par exemple. System.IO est ok, mais System.Lol ne l'est pas.Comment vérifier si chaîne est un espace de nom

Je suppose qu'il faut réfléchir, mais je n'arrive pas à le comprendre.

Des pensées?

Répondre

4

Votre question: « Comment vérifier si la chaîne est un espace de nom » est uniquement valable si l'on considère vous vérifiez pour espaces de noms.

Les espaces de noms sont des préfixes aux noms de classes et les classes sont étendues à un assembly. Pour vérifier si un espace de noms existe, vous devez décider quels assemblages vous êtes prêt à rechercher pour trouver l'existence de l'espace de noms.

Une fois que vous avez décidé que les assemblées que vous êtes prêt à regarder à travers, vous pouvez itérer à travers eux pour l'existence d'un espace de nom particulier comme ceci:

public bool NamespaceExists(IEnumerable<Assembly> assemblies, string ns) 
{ 
    foreach(Assembly assembly in assemblies) 
    { 
     if(assembly.GetTypes().Any(type => type.Namespace == ns)) 
      return true; 
    } 

    return false; 
} 
+0

BTW, vous ne pouvez pas utiliser mot-clé réservé 'namespace' comme un nom de variable;) – abatishchev

+0

Juste pour l'exactitude, vous devriez @ -ize le paramètre d'espace de noms, l'espace de noms est un mot-clé C# :) – Marek

+1

Oh, si pointilleux! Je suis assez sûr que la réponse est lisible sans, mais une édition est à vous. :) –

0

Le CLR n'a pas vraiment un concept d '"espaces de noms": ils sont vraiment un peu plus qu'une convention de nommage. Il n'y a donc pas d'API pour "lister les espaces de noms" ou "obtenir des espaces de noms" ou même "obtenir tous les types dans cet espace de noms". Le mieux que vous puissiez faire est de parcourir tous les assemblys chargés, puis de parcourir tous les types exportés dans chacun de ces assemblages et de vérifier si la chaîne donnée est un "préfixe" sur l'un de ces noms de type. J'imagine que cette solution ne serait pas la plus rapide au monde, mais elle ne serait pas totalement irréalisable non plus.

-2

Il n'y a pas de réflexion sur les espaces de noms. Les espaces de noms définissent un nom de type complet. Donc ce que vous devez faire est:

  • Énumérer tous types (vous ne spécifiez pas l'ensemble source, disons que .NET Framework, alors vous devez inclure tous les ensembles .NET par défaut (regardez celles référencées par VS lorsque vous créez un projet) ou votre assemblage personnalisé, saisit l'assemblage.
  • Rechercher propriété Namespace sur le type donné

Ce que vous devez utiliser:

Assembly.Load method

Assembly.GetTypes method

Type.Namespace property

2

Pourriez-vous faire?

Assembly asm = Assembly.GetExecutingAssembly(); 
List<string> namespaceList = new List<string>(); 

foreach (Type type in asm.GetTypes()) 
{ 
    namespaceList.Add(type.Namespace); 
} 

Ensuite, vérifiez simplement si la chaîne est dans la liste?

(attention, ce n'est pas testé le code!)

8

Essayez cette approche:

using System.CodeDom.Compiler; 
using System.Linq; 

class NamespaceTester : IDisposable 
{ 
    private CodeDomProvider provider = CodeDomProvider.CreateProvider("c#"); 
    private CompilerParameters settings = new CompilerParameters(); 
    private CompilerResults results; 

    public bool Test(string[] namespaces) 
    { 
     results = provider.CompileAssemblyFromSource(
      settings, 
      namespaces.Select(n => String.Format("using {0};", n)).ToArray()); 
     return results.Errors 
      .OfType<CompilerError>() 
      .Any(e => String.Equals(
       e.ErrorText, 
       "CS0234", 
       StringComparison.Ordinal)); 
    } 

    public void Dispose() 
    { 
     if (results != null) 
     { 
      System.IO.File.Delete(results.CompiledAssembly.Location); 
     } 
    } 
} 

CS0234 est:

Le type ou le nom namespace 'name' ne n'existe pas dans la classe ou l'espace de nom 'scope' (manque-t-il un ensemble référence?)

références personnalisées ajoutant:

settings.ReferencedAssemblies.Add("Foobar.dll") 

Utilisation:

public static void Main(string[] args) 
{ 
    using (var tester = new NamespaceTester()) 
    { 
     var success = tester.Test(new[] { 
      "System.IO", 
      "System.LOL" 
     }); 
    } 
} 
+0

+1 pour l'amusement – Marek

Questions connexes