2

わかりました、明確にするためにコードを編集しました:

質問: from ...の属性[MyAttr("...")]にアクセスするにはどうすればよいですか?TestClassOne/TwoBaseClass.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 メンバーを常に初期化する必要があります。派生を開始するTestClassOneTestClassTwo、メンバーを初期化する共通クラスから派生する場合、このコードは壊れます。

リフレクションを巧みに使用すると、上記のコードを拡張してより多くのユースケースをカバーできますが、それはこの質問の範囲を超えています。

編集2:

いいえ、申し訳ありませんが、あなたがしようとしていることは不可能です。SubClassのインスタンスが他のオブジェクトのメンバー フィールドで宣言されているか、配列の要素で宣言されているか、スタック内の一時変数で宣言されているかなどを知る「通常の」方法はありません。そのため、そのインスタンスがそれを宣言しているメンバー フィールドの属性にアクセスする方法はありません。

(ガベージ コレクターにアクセスして、オブジェクトがメモリ内のどこにあるかを調べたいと思うかもしれませんがthis、それはおそらくこの問題の範囲を超えており、いずれにせよ、私が行う方法を知っているわけではありません。)

あなたの問題は完全に他の場所にあると思います。TestClassOne顧客に共通の抽象クラスを作成してTestClassTwo派生させる必要があるかもしれません。たぶん、彼らは自分自身から派生する必要があります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 に答える