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

3
我已经定义了一个程序集级别的特性类 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,但我想确保我没有忽略任何微妙之处。

2个回答

4
将其设为internal(你已经声明不想这样做)是最简单的方法。对于大部分代码,允许MyClass通过静态属性公开类型实例(即public static Type MysteryType { get { return typeof(Mystery); } }),但在属性中无法使用该方法(只有几种基本类型的常量值才能使用)。
那么,替代internal的唯一选择就是将其编码为字符串文字(即[Foo("Bar.MyClass+Mystery")]),并使用typeof(MyClass).Assembly.GetType(fullName) - 但这样会失去typeof通常提供的编译器验证。(请注意运行时使用+表示嵌套类型,而不是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
        {
        }
    }
}

1
这应该是 Bar+Baz,而不是 Bar.Baz,对吧? - Marc Gravell
马克发现得真好!已更新答案。 - MattDavey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接