开发者

How to reference the type of a private class from an assembly-level attribute?

I have defined an assembly level attribute class FooAttribute like this:

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

and I use it to associate an id to classes, for instance:

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

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

This all works fine. But what if I need to somehow reference the private class Mystery, defi开发者_运维百科ned in MyClass? Is this at all possible? Trying to reference it from the top-level [assembly: ...] directive does not work, as the type is not publicly visible:

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

And trying to put the [assembly: ...] directive into MyClass in so that it could see Mystery is not legal, as [assembly: ...] must be defined at the top level:

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

There is a way to access internal types from outside of an assembly by declaring the user a friend of the assembly, but how about referencing private types inside an assembly? I guess it is not possible, and I just would have to declare Mystery to be internal instead, but I want to be sure I did not miss some subtlety.


Making it internal (which you already state you don't want to do) is the least effort approach. For the majority of code, allowing MyClass to expose (via a static property) the type instance (i.e. public static Type MysteryType { get { return typeof(Mystery); } } would work, but that won't work from an attribute (only constant values of a few basic types can be used).

The only alternative to internal, then, is to code it as a string literal, (i.e. [Foo("Bar.MyClass+Mystery")]) and use typeof(MyClass).Assembly.GetType(fullName) - but then you lose the compiler validation that typeof normally provides. (note also the + that the runtime uses to represent nested types, not . which is the C# representation)

Personally, I'd just make it internal.


Your assertions in your last paragraphs are correct. Your options would be to:

  • Make the nested class internal to enable typeof

or

  • Have an added constructor to FooAttribute which takes the fully qualified type name of the private nested class, and then uses reflection to get a System.Type representing it.

For instance:

public sealed class FooAttribute
{
    public FooAttribute(string id, string typeName)
    {
        var type = Type.GetType(typeName);

        // whatever the other ctor does with the System.Type...
    }
}

usage:

[assembly: Foo("Bar", typeof(Bar))]
[assembly: Foo("Baz", "Foo.Bar+Baz, MyAssembly")]

namespace Foo
{
    public class Bar
    {
        private class Baz
        {
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜