2010-11-26 7 views
14

Necesito una instancia de clase/modelo (para el propósito de acceder a un miembro no estático) dentro de mi atributo personalizado.Pase la instancia de Clase como parámetro al constructor de Atributo

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


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

Hay una forma de hacerlo sin usar new() o Reflection.

Respuesta

13

Eso es totalmente imposible. Los atributos se procesan en los metadatos del ensamblado en tiempo de compilación, por lo que hablar sobre pasar una instancia de una clase a un atributo no tiene ningún sentido porque las instancias solo existen en el tiempo de ejecución.

Por otro lado, los atributos siempre se consumen por reflexión, por lo que supongo que en este momento está comprobando la presencia de este atributo personalizado en los metadatos de clase, podría usar la instancia.

+0

¿Hay una manera de pasar los datos a partir del atributo de la instancia de clase o método? (por ejemplo, ¿puede un atributo realizar la autenticación y pasar el usuario autenticado al método?) –

+1

Y esa es la limitación total, una de las mayores limitaciones de C#/.NET que he encontrado hasta ahora. Muy decepcionado. – liang

2

Solo puede usar primitivas o matrices de primitivas como parámetros de atributo, esto es porque deben estar 'alineadas' por el compilador en tiempo de compilación.

3

Impossible man, no puede pasar instancia, delegar, expresión lambda en el constructor de Attribute. Algunos discuten al respecto en here

0

https://msdn.microsoft.com/en-us/library/aa288454(v=vs.71).aspx Basado en MSDN, no se puede hacer por completo si necesita pasar una instancia de clase para procesar aquí.

parámetros de atributos están restringidas a valores constantes de los siguientes tipos: tipos simples (bool, byte, char, short, int, long, float y doble) enumeraciones cadena System.Type objeto (el argumento de un parámetro atributo de tipo de objeto debe ser un valor constante de uno de los tipos anteriores.) matrices unidimensionales de cualquiera de los tipos

Además anteriores, ¿podría explicar por qué nos encontramos en el contexto de atributos y necesidad obtener información de su propio objeto. Suena extraño porque a menudo utilizamos Attribute para explicar más información sobre el objeto pero no para leer datos del objeto.

0

Para acceder a un miembro no estático necesita crear una instancia de una clase en tiempo de ejecución. Tengo una solución para esto. Si desea utilizar una instancia de una clase específica, puede administrar una instancia nueva basada en el tipo específico enumerado o representado como una enumeración.

Utilicé el patrón de fábrica, el patrón de estrategia y la técnica de reflexión para hacer eso. El patrón de estrategia consiste en implementar diferentes algoritmos para envolver cada clase con el tipo de enumeración, mientras que la clase de fábrica debe ser responsable de registrar todos los tipos de clases implementadas y crear el adecuado en el tiempo de ejecución en función del atributo definido. Puede ser complejo al principio, sin embargo, se hizo obvio obtenerlo más tarde.Aquí está un ejemplo práctico:

  • continuación se muestran todos los tipos de validación representados en una enumeración

    [Flags] 
    public enum AlgorithmTypes 
    { 
        None = 0, 
        All = 1, 
        AtLeastOne = 2 
    } 
    
  • Ahora envuelva todos ellos en un patrón de estrategia:

    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); 
    } 
    
  • Ahora aquí es el patrón de fábrica que es responsable de crear la instancia correcta para usted:

    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"); 
        } 
    } 
    
  • Ahora el atributo de validación se puede usar sobre las clases, el constructor acepta un AlgorithmType que va a especificar más adelante qué algoritmo debe ser recogido y llamado.

    [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); 
        } 
    }  
    
Cuestiones relacionadas