如何从程序集级别属性引用私有类的类型

本文关键字:类型 引用 属性 程序集 | 更新日期: 2023-09-27 18:06:55

我已经像这样定义了一个汇编级属性类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 { }
    }
}

这一切都很好。但是,如果我需要以某种方式引用私有类Mystery,在MyClass中定义呢?这有可能吗?试图从顶级[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,但我想确保我没有错过一些微妙之处。

如何从程序集级别属性引用私有类的类型

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

那么,internal的唯一替代方案是将其编码为字符串文字(即[Foo("Bar.MyClass+Mystery")])并使用typeof(MyClass).Assembly.GetType(fullName) -但这样您就失去了typeof通常提供的编译器验证。(请注意运行时用来表示嵌套类型的+,而不是c#表示的.)

我个人就把它改成internal

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

  • 使嵌套类内部启用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
        {
        }
    }
}