【问题标题】:How to reference the type of a private class from an assembly-level attribute?如何从程序集级属性中引用私有类的类型?
【发布时间】:2011-11-06 14:49:18
【问题描述】:

我已经定义了一个程序集级属性类FooAttribute,如下所示:

namespace Bar
{
    [System.AttributeUsage (System.AttributeTargets.Assembly, AllowMultiple=true)]
    public sealed class FooAttribute : System.Attribute
    {
        public FooAttribute(string id, System.Type type)
        {
            // ...
        }
    }
}

我用它来将 id 关联到类,例如:

[assembly: Bar.Foo ("MyClass", typeof (Bar.MyClass))]

namespace Bar
{
    public class MyClass
    {
        private class Mystery { }
    }
}

这一切都很好。但是如果我需要以某种方式引用在MyClass 中定义的私有类Mystery 怎么办?这是可能吗?尝试从顶级 [assembly: ...] 指令引用它不起作用,因为该类型不公开可见:

[assembly: Bar.Foo ("Mystery", typeof (Bar.MyClass.Mystery))] // won't work

并尝试将[assembly: ...] 指令放入MyClass 中,以便它可以看到Mystery 是不合法的,因为[assembly: ...] 必须在顶层定义:

namespace Bar
{
    class MyClass
    {
        [assembly: FooAttribute (...)] // won't work either
        ...
    }
}

有一种方法可以从程序集外部访问internal 类型,方法是将用户声明为程序集的朋友,但是在程序集中引用私有类型怎么样?我想这是不可能的,我只需将Mystery 声明为internal,但我想确保我没有错过一些微妙之处。

【问题讨论】:

    标签: c# attributes class-attributes


    【解决方案1】:

    制作internal(您已经声明您不想这样做)是最省力的方法。对于大多数代码,允许MyClass 公开(通过静态属性)type 实例(即public static Type MysteryType { get { return typeof(Mystery); } } 可以工作,但不会一个属性(只能使用少数基本类型的常量值)。

    那么,internal 的唯一替代方法是将其编码为 字符串字面量,(即[Foo("Bar.MyClass+Mystery")])并使用typeof(MyClass).Assembly.GetType(fullName) - 但随后您将失去@ 987654327@ 通常提供。 (还要注意运行时用来表示嵌套类型的 +,而不是 C# 表示的 .

    就我个人而言,我会选择internal

    【讨论】:

      【解决方案2】:

      您在最后几段中的断言是正确的。您的选择是:

      • 将嵌套类设为内部以启用typeof

      • FooAttribute 添加了一个构造函数,它采用私有嵌套类的完全限定类型名称,然后使用反射来获得一个代表它的System.Type

      例如:

      public sealed class FooAttribute
      {
          public FooAttribute(string id, string typeName)
          {
              var type = Type.GetType(typeName);
      
              // whatever the other ctor does with the System.Type...
          }
      }
      

      用法:

      [assembly: Foo("Bar", typeof(Bar))]
      [assembly: Foo("Baz", "Foo.Bar+Baz, MyAssembly")]
      
      namespace Foo
      {
          public class Bar
          {
              private class Baz
              {
              }
          }
      }
      

      【讨论】:

      • 应该是Bar+Baz,而不是Bar.Baz,确定吗?
      • 很好看的马克!更新了答案
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      • 2018-12-15
      • 2020-08-24
      • 1970-01-01
      相关资源
      最近更新 更多