给定System.Reflection.Assembly的实例。
当我想通过清单资源清单的资源流从当前程序集中加载资源时,我已经遇到过很多难题。
事实是,如果使用Visual Studio将文件作为资源嵌入到程序集中,其清单资源名称将来自Visual Studio项目中定义的程序集的默认名称空间。
我想出的最好的解决方案(避免将默认名称空间硬编码为某个字符串)只是确保始终在默认名称空间中的类内部发生资源加载代码,然后采用以下通用方法可能用过了。
本示例正在加载嵌入式模式。
1 2 3 4 5 6 7
| 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); |
另请参阅:如何获取程序集的命名空间?
编辑:还注意到我在http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/3a469f5d-8f55-4b25-ac25-4778f260bb7e回答的问题的非常详细的答案
如果有人遇到相同的问题,请进行另一种编辑:解决此处资源加载问题的好主意:如何获取项目csproj的默认名称空间(VS 2008)
不可能。什么都没有指定"根"命名空间。选项中的默认名称空间是Visual Studio内容,而不是.net内容。
给定程序集中可以有任意数量的命名空间,并且不需要它们全部从一个公共根开始。最好的办法是反映程序集中的所有类型,并建立其中包含的唯一名称空间的列表。
程序集不一定具有根名称空间。命名空间和程序集是正交的。
您可能正在寻找的是在该Assembly中找到一个类型,然后找出其命名空间是什么。
您应该能够通过使用GetExportedTypes()成员,然后使用返回的Type句柄之一中的Namespace属性来完成此操作。
同样,不能保证所有类型都在相同的名称空间(甚至在相同的名称空间层次结构中)。
我刚刚创建了一个名为Root的空内部类,并将其放在项目根目录中(假设这是您的根名称空间)。然后在需要根名称空间的地方使用它:
当然,我最终得到的是未使用的文件,但是很干净。
frm是启动表单
获取类型为您提供了在程序集中定义的Type对象的列表。该对象具有名称空间属性。请记住,程序集可以具有多个名称空间。
这是获取网站项目的根名称空间的一种非常简单的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ''' <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 |
这只是检查所有已加载的程序集是否为" MyProject"类型,并返回该类型的根名称空间。当您在一个共享日志系统的解决方案中有多个Web项目时,这对于日志记录很有用。希望这对某人有帮助。
希望在这里添加所有其他答案,而无需重复信息,这是我使用Linq解决的方法。我的情况类似于丽莎的答案。
我的解决方案带有以下警告:
-
您正在使用Visual Studio,并为您的项目定义了一个根命名空间,由于您使用了术语"根命名空间",因此我假设这是您所要的
-
您不是从引用程序集中嵌入互操作类型
1 2 3 4 5 6 7 8 9 10 11
| 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
)
) |
我当时想到的问题是:"如果我将库代码调用N个方法更深,并想要该项目的名称空间-例如实际运行的MVC应用程序-我该如何获得它?"
有点骇人听闻,但您可以抓取stacktrace和进行过滤:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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;
} |
所有要做的就是获取stacktrace,从最近调用的方法到根方法运行,并对System进行过滤。找到系统调用后,便知道它已经走得太远了,并向您返回紧接其上方的名称空间。无论您是运行单元测试,MVC App还是服务,系统容器都将比项目的根名称空间深一层。
在某些情况下,系统代码是跟踪的中介(例如System.Task),这将返回错误的答案。我的目标是例如使用一些启动代码,并让它轻松地在根命名空间中查找类或Controller或其他内容,即使执行工作的代码位于库中也是如此。这样就完成了这项任务。
我确信可以改进-我确信可以通过多种方式改进这种怪异的处事方式,并且欢迎进行改进。
我在WPF应用程序中使用typeof(App).Namespace。
应用程序类对于任何WPF应用程序都是必需的,它位于根目录中。
通过枚举程序集清单资源的名称,实际上有一种间接的方式来获取它。您想要的名称以您知道的部分结尾。
而不是在此处重复代码,请参阅获取Assembly.GetManifestResourceStream()方法的默认名称空间名称
命名空间与程序集无关-命名空间与程序集中的类之间的任何映射纯粹是由于命名约定(或巧合)。