【发布时间】:2011-02-06 01:44:10
【问题描述】:
我有一个字符串,我想检查它是否代表正确的命名空间,例如。 System.IO 可以,但System.Lol 不行。
我想应该使用一些反射,但我想不通。
有什么想法吗?
【问题讨论】:
标签: c# .net namespaces
我有一个字符串,我想检查它是否代表正确的命名空间,例如。 System.IO 可以,但System.Lol 不行。
我想应该使用一些反射,但我想不通。
有什么想法吗?
【问题讨论】:
标签: c# .net namespaces
CLR 并没有真正的“命名空间”概念:它们实际上只不过是一种命名约定。因此没有 API 可以“列出命名空间”或“获取命名空间”甚至“获取此命名空间中的所有类型”。
您可以做的最好的事情是遍历所有加载的程序集,然后遍历每个程序集中的所有导出类型,并检查给定字符串是否是任何这些类型名称的“前缀”。我想这个解决方案不会是世界上最快的,但也不会完全不可行。
【讨论】:
没有对命名空间的反射。命名空间定义完整的类型名称。所以你需要做的是:
你需要使用什么:
【讨论】:
你能做到吗?
Assembly asm = Assembly.GetExecutingAssembly();
List<string> namespaceList = new List<string>();
foreach (Type type in asm.GetTypes())
{
namespaceList.Add(type.Namespace);
}
然后只检查字符串是否在列表中?
(请注意,这不是经过测试的代码!)
【讨论】:
试试这个方法:
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 在哪里:
类型或命名空间名称“name”确实 在类或命名空间中不存在 “范围”(您是否缺少程序集 参考?)
自定义引用添加:
settings.ReferencedAssemblies.Add("Foobar.dll")
用法:
public static void Main(string[] args)
{
using (var tester = new NamespaceTester())
{
var success = tester.Test(new[] {
"System.IO",
"System.LOL"
});
}
}
【讨论】:
您的问题“如何检查字符串是否为名称空间”仅在您考虑 where 您正在检查名称空间时才有效。
命名空间是类名的前缀,类的作用域是程序集。要检查命名空间是否存在,您需要确定准备查看哪些程序集以查找命名空间的存在。
一旦您决定了准备查看哪些程序集,您就可以遍历它们以确定是否存在特定的命名空间,如下所示:
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;
}
【讨论】:
namespace作为变量名;)
return assemblies.SelectMany(a => a.GetTypes()).Any(t => t.Namespace == ns)