2012-09-23 3 views
2

Ok, édité le code de clarification:Être attribut personnalisé de SubClass à BaseClass (C# .NET 4.0)

Question: Comment puis-je accéder à l'attribut [MyAttr("...")] dans TestClassOne/Two de BaseClass.TheAttribute ...?

Toutes les classes à l'exception de TestClassOne/Two seront compilées dans mon "core" et livrées en tant que plate-forme de développement à un client. Le TestClassOne/Two est développé par le client, de sorte qu'il ne peut y avoir aucune connaissance du TestClassOne/Two dans le "noyau".

Le code ci-dessous est compilé en "core" et livré au client en tant que 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 
{ 

} 

code ci-dessous est développé par le client (à l'aide de mon dll)

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

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

je poser une autre question à http://stackoverflow.com/questions/12569139/how-to-get-which-type-of-parent- object-to-reference-the-current-object-through-prope. Si vous répondez à cette question, vos questions recevront sûrement une réponse. –

Répondre

2

Edition 3:

Vous pouvez marcher la pile d'appel, à la recherche d'un attribut pertinent dans un membre concerné dans une classe pertinente. Essayez ceci:

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; 
     } 
    } 
} 

Cela exige que votre client toujours membre initialise de SubClass dans la classe qui le déclare. Si elles commencent à dériver TestClassOne ou l'ont et TestClassTwo dérivent d'une classe commune qui initialise le membre, ce code va se casser. Avec l'utilisation intelligente de la réflexion, vous pouvez étendre le code ci-dessus pour couvrir plus de cas d'utilisation, mais cela dépasse le cadre de cette question.

Edit 2:

Non, je suis désolé, mais ce que vous essayez de faire est impossible. Il n'existe aucun moyen "normal" pour une instance de SubClass de savoir si elle est déclarée dans un champ membre d'un autre objet, ou dans un élément d'un tableau ou dans une variable temporaire de la pile, ou autre. En tant que tel, il n'y a aucun moyen pour cette instance d'accéder aux attributs du champ membre qui le déclare.

(je suppose que vous pouvez essayer d'accéder au garbage collector pour savoir où en mémoire la vie de l'objet this, mais c'est probablement bien au-delà de la portée de ce problème, et en tout cas, pas quelque chose que je sais comment fais.)

Je soupçonne que votre problème est entièrement ailleurs. Peut-être que vous devez demander à votre client de faire TestClassOne et TestClassTwo dériver d'une classe abstraite commune. Peut-être qu'ils doivent dériver de BaseClass eux-mêmes. Peut-être que vous devez ajouter des paramètres au constructeur. Peut-être que vous devez fournir une interface différente. Nous ne pouvons pas savoir si vous fournissez plus d'informations sur vos besoins spécifiques.

Edit:

Pour accéder aux attributs déclarés sur le membre MyTest, essayez quelque chose le long de ces lignes:

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

Cela recherche classe Test pour un membre du même type que this et recherchez les attributs sur ce membre.

(je n'ai pas mon Visual Studio ici, pour vérifier la syntaxe Where exacte, mais il devrait être assez proche de celle ...)

Réponse d'origine:

Votre attribut est déclaré sur le MyTest membre de la classe Test. Mais, vous faites GetCustomAttributes sur la classe SubClass lui-même.

Essayez ceci:

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

} 

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

Si vous obtenez ce que vous voulez.

+0

Merci d'avoir répondu, mais l'attribut doit malheureusement être déclaré dans la classe Test. Est-il possible d'accéder aux attributs déclarés sur le membre "MyTest" dans la classe Test? –

+0

Merci encore, mais cela nécessite une connaissance du type "Test" dans BaseClass. La pensée est que tout sauf "Test" devrait être précompilé et que je peux créer plusieurs autres classes comme "Test" et que mon BaseClass peut travailler avec tous. –

+0

@MattiasRundqvist: à quoi ressemble l'entrée de la classe Test? –

2

Vous pouvez obtenir directement à partir du type Test:

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

Merci d'avoir répondu, mais cela ne marchera pas dans mon cas. Cela nécessite une connaissance du type "Test" dans BaseClass. La pensée est que tout sauf "Test" devrait être précompilé et que je peux créer plusieurs autres classes comme "Test" et que mon BaseClass peut travailler avec tous. –

+0

@MattiasRundqvist: Vous devez modifier votre question pour afficher un échantillon plus clair –

+1

Modifié le code. J'espère avoir réussi à clarifier mon problème maintenant. –

Questions connexes