【问题标题】:Get custom attribute from SubClass in BaseClass (C# .NET 4.0)从 BaseClass 中的子类获取自定义属性(C# .NET 4.0)
【发布时间】:2012-09-15 04:21:42
【问题描述】:

好的,为了澄清,编辑了代码:

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

除 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();
}

【问题讨论】:

标签: c# inheritance attributes custom-attributes


【解决方案1】:

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

原答案:

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

试试这个:

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

}

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

应该得到你想要的。

【讨论】:

  • 感谢您的回答,但不幸的是该属性必须在 Test 类中声明。有没有办法访问在 Test 类中的“MyTest”成员上声明的属性?
  • 再次感谢,但这需要了解 BaseClass 中的“测试”类型。想法是除了“Test”之外的所有东西都应该被预编译,我可以创建更多的类,比如“Test”,并且我的 BaseClass 可以与它​​们一起使用。
  • @MattiasRundqvist:Test 类的输入是什么样的?
  • 我不确定你的意思...?除 TestClassOne/Two 之外的所有类都将编译到我的“核心”中,并作为开发平台交付给客户。 TestClassOne/Two是客户自己开发的,所以“核心”中不可能有TestClassOne/Two的知识。
  • 您不断更改要求。你想做的事情是不可能的。我会在编辑中做一个注释。
【解决方案2】:

可以直接从输入Test获取:

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

【讨论】:

  • 感谢您的回答,但这不适用于我的情况。这需要了解 BaseClass 中的“测试”类型。想法是除了“Test”之外的所有东西都应该被预编译,我可以创建更多的类,比如“Test”,并且我的 BaseClass 可以与它​​们一起使用。
  • @MattiasRundqvist:您应该编辑您的问题以显示更清晰的示例
  • 编辑了代码。希望我现在设法让我的问题更清楚。
猜你喜欢
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多