2

好的,编辑了代码以进行澄清:

问题:如何[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();
}
4

2 回答 2

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语法,但它应该非常接近......)

原答案:

您的属性是在MyTestclass 的成员上声明的Test。但是,你GetCustomAttributes在上课SubClass本身。

尝试这个:

[MyAttr("apa")]
public class SubClass : BaseClass
{

}

public class Test
{
    public SubClass MyTest = new SubClass();
}

应该得到你想要的。

于 2012-09-23T13:20:08.630 回答
2

您可以直接从 type 获取Test

var result = typeof (Test)
               .GetField("MyTest", BindingFlags.Public | BindingFlags.Instance)
               .GetCustomAttribute<MyAttr>();
于 2012-09-23T13:22:53.137 回答