2010-11-26 37 views
14

Ich brauche eine Instanz der Klasse/des Modells (für den Zugriff auf ein nicht statisches Element) innerhalb meines benutzerdefinierten Attributs.Übergabe der Instanz der Klasse als Parameter an den Attributkonstruktor

public class LoginModel 
{ 
    [AutoComplete(currentInstance)] //pass instance of class or CompanyNames 
    public string DepartmentName { get; set; } 


    public string[] DepartmentNames { get {...} } 
} 

Gibt es eine Möglichkeit, dies ohne Verwendung von new() oder Reflection zu tun.

Antwort

13

Das ist total unmöglich. Attribute werden zur Kompilierungszeit in die Metadaten der Assembly eingebunden, sodass es keinen Sinn ergibt, eine Instanz einer Klasse an ein Attribut weiterzuleiten, da Instanzen nur zur Laufzeit existieren.

Auf der anderen Seite werden Attribute immer durch Reflektion verbraucht, also denke ich, dass Sie in dem Moment, in dem Sie nach dem Vorhandensein dieses benutzerdefinierten Attributs in den Klassenmetadaten suchen, die Instanz verwenden könnten.

+0

Gibt es eine Möglichkeit, Daten aus dem Attribut der Klasseninstanz oder Methode zu übergeben? (z. B. kann ein Attribut Authentifizierung tun und übergibt den authentifizierten Benutzer an die Methode?) –

+1

Und das ist die totale Einschränkung, eine der größten C# /. NET Einschränkungen, die ich bisher begegnet bin. Sehr enttäuscht. – liang

2

Sie können nur Primitive oder Arrays von Primitiven als Attributparameter verwenden, da sie vom Compiler zur Kompilierungszeit "inline" sein müssen.

3

Unmöglich man, können Sie nicht übergeben Instanz, Delegate, Lambda-Ausdruck in den Konstruktor des Attributs. Einige diskutieren darüber bei here

0

https://msdn.microsoft.com/en-us/library/aa288454(v=vs.71).aspx Basierend auf MSDN, kann es absolut nicht getan, wenn Sie brauchen eine Instanz der Klasse passieren hier zu verarbeiten.

Attribut Parameter werden auf konstante Werte der folgenden Typen beschränkt: Einfache Typen (Bool, Byte, char, short, int, long, float und double) string System.Type Aufzählungen Objekt (das Argument ein Attribut Parameter des Typs Objekt muss ein konstanter Wert eines den obigen Typen sein.) eindimensionale Anordnungen von einer der oben genannten Typen

Außerdem könnten Sie erklären, warum wir in Attribut Kontext und Bedarf stehen Informationen von ihrem eigenen Objekt erhalten. Es klingt seltsam, weil wir Attribute häufig verwenden, um mehr Informationen über Objekte zu erklären, aber nicht, um Objektdaten zu lesen.

0

Für den Zugriff auf ein nicht statisches Member müssen Sie eine Klasse zur Laufzeit instanziieren. Ich habe einen Workaround dafür. Wenn Sie eine Instanz einer bestimmten Klasse verwenden möchten, können Sie eine neue Instanz basierend auf dem bestimmten Typ instanziieren, der als Aufzählung aufgelistet oder dargestellt wird.

Ich habe Factory Pattern, Strategie Pattern und Reflection-Technik verwendet, um das zu tun. Strategy Pattern ist die Implementierung verschiedener Algorithmen mit Wrapping jeder Klasse mit Aufzählungstyp, während die Factory-Klasse dafür verantwortlich sein sollte, alle Typen von implementierten Klassen zu registrieren und zur Laufzeit basierend auf dem definierten Attribut das passende zu erstellen. Es könnte am Anfang komplex sein, aber es wurde offensichtlich, es später zu bekommen.Hier ist ein Beispiel aus der Praxis:

  • Hier sind alle Prüfungstypen in einer Aufzählung dargestellt

    [Flags] 
    public enum AlgorithmTypes 
    { 
        None = 0, 
        All = 1, 
        AtLeastOne = 2 
    } 
    
  • nun alle von ihnen wickelt in einem Strategiemuster:

    public class NoneValidationMode : RequiredValidationMode 
    { 
        public NoneValidationMode() { } 
        public override bool IsValid(string properties, object value) 
        { 
         //validation code here 
        } 
    } 
    
    public class AllValidationMode: RequiredValidationMode 
    { 
        public override bool IsValid(string properties,object value) 
        { 
         //validation code here 
        } 
    } 
    
    public class AtLeastOneValidationMode : RequiredValidationMode 
    { 
        public override bool IsValid(string properties, object value) 
        { 
         //validation code here 
        } 
    } 
    public abstract class RequiredValidationMode 
    { 
        public abstract bool IsValid(string properties, object value); 
    } 
    
  • Hier arbeiten ist das Factory-Muster, das für das Erstellen der richtigen Instanz für Sie verantwortlich ist:

    public class AlgorithmStrategyFactory 
    { 
        private static ArrayList _registeredImplementations; 
    
        static AlgorithmStrategyFactory() 
        { 
         _registeredImplementations = new ArrayList(); 
         RegisterClass(typeof(NoneValidationMode)); 
         RegisterClass(typeof(AllValidationMode)); 
         RegisterClass(typeof(AtLeastOneValidationMode)); 
        } 
        public static void RegisterClass(Type requestStrategyImpl) 
        { 
         if (!requestStrategyImpl.IsSubclassOf(typeof(RequiredValidationMode))) 
          throw new Exception("requestStrategyImpl must inherit from class RequiredValidationMode"); 
    
         _registeredImplementations.Add(requestStrategyImpl); 
        } 
        public static RequiredValidationMode Create(AlgorithmTypes algorithmType) 
        { 
         // loop thru all registered implementations 
         foreach (Type impl in _registeredImplementations) 
         { 
          // get attributes for this type 
          object[] attrlist = impl.GetCustomAttributes(true); 
    
          // loop thru all attributes for this class 
          foreach (object attr in attrlist) 
          { 
           if (attr is AlgorithmAttribute) 
           { 
            if (((AlgorithmAttribute)attr).AlgorithmType.Equals(algorithmType)) 
            { 
             return (RequiredValidationMode)System.Activator.CreateInstance(impl); 
            } 
           } 
          } 
         } 
         throw new Exception("Could not find a RequiredValidationMode implementation for this AlgorithmType"); 
        } 
    } 
    
  • Jetzt Validierungsattribut kann über Klassen verwendet werden, Konstruktor akzeptiert einen AlgorithmType, der später angeben wird, welcher Algorithmus aufgerufen und aufgerufen werden soll.

    [AttributeUsage(AttributeTargets.Class, AllowMultiple =false)] 
    public class MyAttribute : ValidationAttribute 
    { 
        AlgorithmTypes AlgorithmType; 
    
        public MyAttribute(AlgorithmTypes algorithm = AlgorithmTypes.None) 
        { 
         AlgorithmType = algorithm; 
        } 
    
        public override bool IsValid(object value) 
        { 
    
         return (AlgorithmStrategyFactory.Create(AlgorithmType)).IsValid(Properties, value); 
        } 
    }  
    
Verwandte Themen