【问题标题】:How do you get the root namespace of an assembly?如何获取程序集的根命名空间?
【发布时间】:2010-09-10 21:53:45
【问题描述】:

给定一个System.Reflection.Assembly的实例。

【问题讨论】:

    标签: .net reflection


    【解决方案1】:

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

    事实是,如果您使用 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);
    

    另请参阅:How to get Namespace of an Assembly?

    编辑:还注意到我在http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/3a469f5d-8f55-4b25-ac25-4778f260bb7e回答的问题的非常详细的答案

    另一个编辑,以防有相同问题的人来找:解决资源加载问题的好主意:How get the default namespace of project csproj (VS 2008)

    【讨论】:

    • 当程序集名称与我的项目的“根命名空间”不匹配时,嵌入式资源解析出现问题。感谢您的有用帖子
    • 你不能创建一个没有命名空间的类并使用 typeof(DefaultNamespaceHelper).Namespace 吗?
    • 这个答案不应该得到支持,因为它会误导那些寻找实际问题答案的人。这个答案仅仅得到了你所在类的命名空间。它绝对没有得到当前程序集的根命名空间,这就是问题所在。 Darren 的accepted answer 是正确的。
    • @Neo 您描述的所有警告都已经在答案中提出。当然它回答了一个不同的问题,但人们来到这里试图回答我正在回答的问题。这对想知道如何找到他们所在类的命名空间的人很有帮助。
    【解决方案2】:

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

    【讨论】:

    • 来自用户 Lisa 的以下帖子实际上有效,因此此答案被标记为答案,但没有正当理由。
    • @Roboblob Darren 的回答在技术上是正确的。我的只是在 95% 左右的情况下有用,你想在 VS 中构建项目的上下文中了解这一点。
    • 只是因为想象力的失败而无法实现。见stackoverflow.com/questions/4885888/…
    • 从 Lisa 的回答来看,这是一个 .NET 的东西。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

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

      typeof(Root).Namespace;
      

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

      【讨论】:

      • 在同一个程序集中需要这个但不想硬编码时很有用。
      【解决方案5】:

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

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

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:
            GetType(frm).Namespace
            

            frm是启动表单

            【讨论】:

            • 启动表单不在根命名空间怎么办?
            【解决方案9】:

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

            【讨论】:

            • 虽然我同意,但值得注意的是,Visual Studio 项目具有默认命名空间,如果您使用 Visual Studio 嵌入资源,则该资源的清单资源名称派生自默认命名空间,并且会显示为如果您始终使用 Visual Studio 构建程序集,则由程序集本身定义。让我们面对现实吧,这很常见。
            【解决方案10】:

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

            这里不再重复代码,请看get Default namespace name for Assembly.GetManifestResourceStream() method

            【讨论】:

              【解决方案11】:

              我遇到的问题是,“如果我深入调用库代码 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;
                  }
              

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

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

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

              【讨论】:

                【解决方案12】:

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

                我的解决方案有以下注意事项:

                • 您正在使用 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
                        )
                )
                

                【讨论】:

                  【解决方案13】:

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

                  ''' <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 项目时,这对于日志记录非常有用。希望这对某人有所帮助。

                  【讨论】:

                    【解决方案14】:

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

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

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2010-10-13
                      • 1970-01-01
                      • 2010-09-23
                      • 1970-01-01
                      • 1970-01-01
                      • 2019-02-02
                      • 2010-10-14
                      相关资源
                      最近更新 更多