2010-11-10 22 views
12

Dado un ejemplo como ..El uso de atributos para las restricciones genéricas

public interface IInterface { } 

public static void Insert<T>(this IList<T> list, IList<T> items) where T : IInterface 
{ 
// ... logic 
} 

Esto funciona bien, pero me preguntaba si es posible utilizar un atributo como una restricción. Tal como ...

class InsertableAttribute : Attribute 

public static void Insert<T>(this IList<T> list, IList<T> items) where T : [Insertable] 
{ 
// ... logic 
} 

Obviamente esta sintaxis no funciona, o no estaría publicando la pregunta. Pero solo tengo curiosidad si es posible o no, y cómo hacerlo.

+2

Me gustaría * AMAR * si esto se implementó ... – tenfour

Respuesta

11

No. Solo puede usar clases (base) e interfaces como restricciones.

sin embargo, puede hacer algo como esto:

public static void Insert<T>(this IList<T> list, IList<T> items) 
{ 
    var attributes = typeof(T).GetCustomAttributes(typeof(InsertableAttribute), true); 

    if (attributes.Length == 0) 
     throw new ArgumentException("T does not have attribute InsertableAttribute"); 

    /// Logic. 
} 
+0

Gracias. Esto es lo que pensé, pero pensé que valía la pena intentarlo. Mi proyecto no lo necesita, pero pensé que era una buena información para saber. Haré clic en la casilla 'Aceptar' en 5 minutos cuando Stack Overflow me lo permita. – Ciel

+0

De nada. –

+0

Si necesita el atributo para algún procesamiento externo, para el cual una interfaz que usted controla es el marcador, puede declarar el atributo en la interfaz y seleccionar atributos heredados. – smartcaveman

7

No. Sólo puede utilizar clases, interfaces, class, struct, new() y otros parámetros de tipo como restricciones.

Si InsertableAttribute especifica [System.AttributeUsage(Inherited=true)], entonces se podría crear una clase ficticia como:

[InsertableAttribute] 
public class HasInsertableAttribute {} 

y luego limitar su método como:

public static void Insert<T>(this IList<T> list, IList<T> items) where T : HasInsertableAttribute 
{ 
} 

Entonces T que siempre tendría el atributo aunque fuera solo viene de la clase base. Las clases de implementación podrían "anular" ese atributo al especificarlo en ellos mismos.

+0

Y otros parámetros de tipo :) –

+0

@Jon Skeet Ah, por supuesto. Sabía que estaba olvidando algo, ¡gracias por señalar eso! –

-1

No, no puedes. Su pregunta no es sobre atributos, sino un diseño orientado a objetos. Lea lo siguiente para obtener más información sobre generic type constraint.

Prefiero sugiero que haga lo siguiente:

public interface IInsertable { 
    void Insert(); 
} 

public class Customer : IInsertable { 
    public void Insert() { 
     // TODO: Place your code for insertion here... 
    } 
} 

Así que la idea es tener una interfaz IInsertable, e implementa esta interfaz dentro de una clase cada vez que desee ser insertable. De esta manera, restringirá automáticamente la inserción de elementos insertables.

Este es un enfoque más flexible, y le dará la facilidad de persistir la misma o diferente información de una entidad a otra, ya que tiene que implementar la interfaz usted mismo dentro de su clase.

+0

Bueno, no necesito hacerlo en absoluto. Es más de una de esas cosas en las que estás codificando algo, y te golpea como una idea que podría ser útil para otra cosa.En verdad, si tuviera que asegurar la restricción a un atributo, simplemente usaría una clase ficticia. – Ciel

+0

Entiendo tu punto, y hay momentos en los que piensas en algo y te preguntas si es factible. =) Interesante pregunta de todos modos. =) –

Cuestiones relacionadas