tags:

views:

193

answers:

5

Hi, I have a string and I want to check if it represents a proper namespace, eg. System.IO is ok, but System.Lol is not.

I guess some reflection should be used, but I can't figure this out.

Any thoughts?

A: 

The CLR doesn't really have a concept of "namespaces": they're really little more than a naming convention. So there is no API to "list namespaces" or "get namespaces" or even "get all types in this namespace".

The best you could do is loop through all loaded assemblies, then loop through all exported types in each of those assemblies and check whether the given string is a "prefix" on any of those type names. I imagine this solution wouldn't be the fastest in the world, but it wouldn't be totally unworkable, either.

Dean Harding
A: 

There is no reflection on namespaces. The namespaces define full type name. So what you need to do is:

  • Enumerate all types (you do not specify the source set, let's say .NET Framework, then you need to include all the default .NET assemblies (look at those referenced by VS when you create a project), or your custom assembly, then types in the assembly).
  • Look for Namespace property on the given type

What you need to use:

Assembly.Load method

Assembly.GetTypes method

Type.Namespace property

Marek
+1  A: 

Could you do this?

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

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

Then just check to see if the string is in the list?

(Be warned, this isn't tested code!)

Siyfion
+7  A: 

Try this approach:

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

where CS0234 is:

The type or namespace name 'name' does not exist in the class or namespace 'scope' (are you missing an assembly reference?)

Custom references adding:

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

Usage:

public static void Main(string[] args)
{
    using (var tester = new NamespaceTester())
    {
        var success = tester.Test(new[] {
            "System.IO",
            "System.LOL"
        });
    }
}
abatishchev
+1 for amusement
Marek
+2  A: 

Your question "How to check if string is a namespace" is only valid when you consider where you are checking for namespaces.

Namespaces are prefixes to class names, and classes are scoped to an assembly. To check whether a namespace exists, you need to decide which assemblies you are prepared to look through to find the existence of the namespace.

Once you have decided which assemblies you are prepared to look through, you can iterate through them for the existence of a particular namespace like so:

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;
}
Programming Hero
Btw, you can't use reserved keyword `namespace` as a variable name ;)
abatishchev
Just for the sake of correctness, you should @-ize the namespace parameter, namespace is a C# keyword :)
Marek
Oh, so picky! I'm pretty sure the answer is legible without, but an edit is yours. :)
Programming Hero
`return assemblies.SelectMany(a => a.GetTypes()).Any(t => t.Namespace == ns)`
abatishchev