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