从BaseClass中的SubClass获取自定义属性(C#.NET 4.0)

时间:2012-09-23 13:15:43

标签: c# inheritance attributes custom-attributes

好的,编辑了澄清代码:

问题:如何从[MyAttr("...")]中访问TestClassOne/Two中的BaseClass.TheAttribute属性?

除TestClassOne / Two之外的所有类都将编译到我的“核心”中,并作为开发平台提供给客户。 TestClassOne / Two是由客户开发的,因此在“核心”中无法了解TestClassOne / Two。

下面的代码被编译成“核心”并以dll的形式交付给客户。

[TestMethod()]
public void AttrTest()
{
    var one = new TestClassOne();
    var attrOne = one.MyTestProperty.TheAttribute;

    var two = new TestClassTwo();
    var attrTwo = two.MyTestProperty.TheAttribute;
}

public class MyAttr : Attribute
{
    private string _test;
    public MyAttr(string test)
    {
        this._test = test;
    }
}

public class BaseClass
{
    public string TheAttribute
    {
        get { 
            // Here I would like to get the "[MyAttr("...")]" from the classes in the bottom

            return null;
        }
    }
}

public class SubClass : BaseClass
{

}

以下代码由客户(使用我的dll)开发

public class TestClassOne
{
    [MyAttr("Attribute one")]
    public SubClass MyTestProperty = new SubClass();
}

public class TestClassTwo
{
    [MyAttr("Attribute two")]
    public SubClass MyTestProperty = new SubClass();
}

2 个答案:

答案 0 :(得分:2)

编辑3:

您可以遍历调用堆栈,在相关类中的相关成员中查找相关属性。试试这个:

public class MyAttr : Attribute
{
    private string _test;
    public MyAttr(string test)
    {
        this._test = test;
    }

    public string getAttr()
    {
        return _test;
    }
}


public class BaseClass
{
    private string theString;

    public BaseClass()
    {
        StackTrace callStack = new StackTrace();

        for ( int i = 0; i < callStack.FrameCount; i++ )
        {
            Type t = callStack.GetFrame(i).GetMethod().DeclaringType;
            foreach ( MemberInfo m in t.GetMembers().Where(x => typeof(BaseClass).IsAssignableFrom(x.Type)) )
            {
                foreach ( var z in  m.GetCustomAttributes(typeof(MyAttr)) )
                {
                    MyAttr theAttr = z as MyAttr;
                    if ( z!= null )
                    {
                        theString = z.getAttr();
                        return;
                    }
                }
            }
        }
    }

    public string Test
    {
        get { 
            return theString;
        }
    }
}

这要求您的客户始终在声明它的类中初始化SubClass成员。如果他们开始派生TestClassOne或者拥有它并且TestClassTwo派生自初始化成员的公共类,则此代码将会中断。

通过巧妙地使用反射,您可以扩展上面的代码以涵盖更多用例,但这超出了这个问题的范围。

编辑2:

没有。对不起,但你想做的事情是不可能的。 SubClass的实例没有“正常”的方式来知道它是在某个其他对象的成员字段中声明,还是在数组中的元素中或在堆栈中的临时变量中声明,或者其他什么。因此,该实例无法访问声明它的成员字段的属性。

(我想你可能想尝试访问垃圾收集器来找出this对象所在的内存位置,但这可能超出了这个问题的范围,无论如何,不​​是我的东西知道怎么做。)

我怀疑你的问题完全在别处。也许您需要要求您的客户从一个共同的抽象类派生TestClassOneTestClassTwo。也许他们需要从BaseClass自己派生出来。也许你需要在构造函数中添加参数。也许你需要提供一个完全不同的界面。除非您提供有关您的特定业务要求的更多信息,否则我们无法知道。

修改

要访问在MyTest成员上声明的属性,请尝试以下几行:

public class BaseClass
{
    public string Test
    {
        get { 
            var attr = typeof(Test).GetMembers().Where(x => x.Type == this.GetType()).First().GetCustomAttributes(true);
            return null;
        }
    }
}

这将在类Test中搜索与this类型相同的成员,并在该成员上查找属性。

(我这里没有我的Visual Studio,检查确切的Where语法,但它应该非常接近......)

原始答案:

您的属性在类MyTest的{​​{1}}成员上声明。但是,您正在课堂Test上进行GetCustomAttributes

试试这个:

SubClass

应该得到你想要的东西。

答案 1 :(得分:2)

您可以直接从Test类型获取:

var result = typeof (Test)
               .GetField("MyTest", BindingFlags.Public | BindingFlags.Instance)
               .GetCustomAttribute<MyAttr>();