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);
}
}
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?) –
Und das ist die totale Einschränkung, eine der größten C# /. NET Einschränkungen, die ich bisher begegnet bin. Sehr enttäuscht. – liang