54

给定一个实例System.Reflection.Assembly

4

14 回答 14

71

当我想通过其清单资源流从当前程序集中加载资源时,我多次遇到这种困境。

事实是,如果您使用 Visual Studio 将文件作为资源嵌入到程序集中,则其清单资源名称将派生自 Visual Studio 项目中定义的程序集的默认命名空间。

我想出的最佳解决方案(避免将默认命名空间硬编码为某处的字符串)是简单地确保您的资源加载代码总是从也在默认命名空间中的类内部发生,然后是以下近乎通用的方法可能用过了。

此示例正在加载嵌入式模式。

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)

于 2011-06-07T02:55:57.807 回答
50

不可能。没有指定“根”命名空间。选项中的默认命名空间是 Visual Studio 的东西,而不是 .net 的东西

于 2008-09-18T20:04:46.317 回答
10

给定程序集中可以有任意数量的命名空间,并且没有什么要求它们都从一个共同的根开始。您可以做的最好的事情是反映程序集中的所有类型并构建其中包含的唯一名称空间列表。

于 2008-09-18T20:06:55.673 回答
7

我刚刚创建了一个名为 Root 的空内部类并将其放在项目根目录中(假设这是您的根名称空间)。然后我在需要根命名空间的任何地方使用它:

typeof(Root).Namespace;

当然,我最终得到了一个未使用的文件,但它很干净。

于 2015-11-11T13:24:03.257 回答
5

程序集不一定有根命名空间。命名空间和程序集是正交的。

相反,您可能正在寻找的是在该程序集中找到一个类型,然后找出它的命名空间是什么。

您应该能够通过使用 GetExportedTypes() 成员,然后使用返回的类型句柄之一中的命名空间属性来完成此操作。

同样,不能保证所有类型都在同一个命名空间中(甚至在同一个命名空间层次结构中)。

于 2008-09-18T20:07:28.557 回答
2

Get Types为您提供程序集中定义的Type对象列表。该对象具有命名空间属性。请记住,一个程序集可以有多个命名空间。

于 2008-09-18T20:08:39.333 回答
2
GetType(frm).Namespace

frm是启动表格

于 2014-07-01T15:31:03.987 回答
2

typeof(App).Namespace在我的 WPF 应用程序中使用。App 类对于任何 WPF 应用程序都是必需的,它位于根目录中。

于 2016-03-29T15:20:37.430 回答
0

命名空间与程序集无关 - 命名空间和程序集中的类之间的任何映射纯粹是由于命名约定(或巧合)。

于 2008-09-18T20:34:49.973 回答
0

实际上有一种间接的方法来获取它,通过枚举程序集的清单资源的名称。您想要的名称以您知道的部分结尾。

此处不再重复代码,请参阅获取 Assembly.GetManifestResourceStream() 方法的默认命名空间名称

于 2014-07-31T23:14:52.507 回答
0

我遇到的问题是,“如果我深入调用库代码 N 个方法并想要项目的命名空间——例如实际运行的 MVC 应用程序——我该如何得到它?”

有点hacky,但您可以获取堆栈跟踪和过滤器:

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

所有这一切都是获取堆栈跟踪,运行从最近调用到 root 的方法,并过滤 System. 一旦它找到一个系统调用,它就知道它已经走得太远了,并返回它上面的名称空间。无论您是在运行单元测试、MVC 应用程序还是服务,系统容器都将比项目的根命名空间深 1 级,所以瞧。

在某些情况下,系统代码是跟踪中的中介(如 System.Task),这将返回错误的答案。我的目标是以一些启动代码为例,让它在根命名空间中轻松找到类或控制器或其他任何东西,即使完成工作的代码位于库中。这完成了该任务。

我确信这可以改进 - 我确信这种 hacky 的做事方式可以在很多方面得到改进,并且欢迎改进。

于 2016-05-09T05:52:30.403 回答
0

在此处添加所有其他答案,希望不重复信息,这是我使用 Linq 解决此问题的方法。我的情况与丽莎的回答类似。

我的解决方案附带以下警告:

  • 您正在使用 Visual Studio 并为您的项目定义了一个根命名空间,我认为这是您所要求的,因为您使用术语“根命名空间”
  • 您没有从引用的程序集中嵌入互操作类型
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
        )
)
于 2017-02-22T19:24:07.503 回答
0

这是获取网站项目的根命名空间的一种相当简单的方法。

''' <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 项目共享一个日志系统时,这对于日志记录很有用。希望这可以帮助某人。

于 2017-06-08T20:33:50.190 回答
0

如果您尝试加载嵌入式资源,则此解决方案有效。

var assembly = System.Reflection.Assembly.GetExecutingAssembly();
string[] resourceNames = assembly.GetManifestResourceNames();

string  resourceNameNoNamespace = $"Languages.{languageSupport.IsoCode}.Languages.xml";
var match = resourceNames.SingleOrDefault(rn => rn.EndsWith(resourceNameNoNamespace));
于 2021-12-02T20:20:51.437 回答