2010-10-06 3 views
3

Je souhaite créer une méthode générique applicable uniquement aux classes ayant l'attribut Serializable, par ex.Comment limiter une méthode générique à des classes avec un attribut spécifié?

public static int Foo<T>(T obj) where T : Serializable { 
    ... 
} 

mais évidemment ce qui précède ne compile pas. Et je devine si je mets SerializableAttribute là, il insistera que T est un attribut, pas une classe avec cet attribut.

Comment faites-vous quelque chose comme ça?

+0

Vous ne pouvez pas faire cela. –

Répondre

4

Les contraintes sur les attributs ne peuvent pas être effectuées. Une solution pourrait consister à utiliser la réflexion pour analyser l'objet transmis à votre méthode et voir si l'attribut Serializable est déclaré.

+1

La suggestion de classe de base n'est pas vraiment utile, car il est impératif que la classe feuille déclare également cet attribut. (Après tout, la classe 'Object' elle-même est décorée avec' [Serializable] '.) –

+0

@Kirk - Bravo pour ça, je ne savais pas. Je modifierai ma réponse. –

0

Vous devez faire en sorte que les classes implémentent une interface applique cet attribut. Vous pouvez alors filtrer l'interface:

public static int Foo<T>(T obj) where T : ISerializable 
{} 
2

Vous pouvez implémenter l'interface ISerializable et l'utiliser « où T: ISerializable » mais vous devez mettre en œuvre les méthodes ISerializable dans toutes les classes. Une vérification au moment de l'exécution peut rechercher le SerializableAttribute sur la classe, mais vous n'avez pas de vérification de temps de compilation. Vous pourriez envisager d'écrire votre propre interface qui a très peu à mettre en œuvre, peut-être juste une propriété et implémenter cette interface sur chacune de vos classes. Quelque chose comme ...

public interface ISerializableSet { 
    bool IsSerializable { get; } 
} 

Votre mise en œuvre pourrait utiliser la réflexion puis de faire une vérification de l'exécution, votre méthode Foo serait déclarée « où T: ISerializableSet » pour votre chèque de compilation.

Voici un exemple plus complet ...

public interface ISerializableSet 
{ 
    bool IsSerializable { get; } 
} 

[Serializable] 
class SerializableClass : ISerializableSet 
{ 
    [NonSerialized] 
    private bool _runTimeCheck = true; 

    #region ISerializableSet Members 
    public bool IsSerializable 
    { 
     get { 
      if(!_runTimeCheck) 
       return true; 
      if(0 != (this.GetType().Attributes & System.Reflection.TypeAttributes.Serializable)) 
       return true; 
      return false; 
     } 
    } 
    #endregion 
} 

public static class Bar2 
{ 
    public static int Foo<T>(T obj) where T : ISerializableSet 
    { 
     ISerializableSet sc = obj; 
     Console.WriteLine("{0}", sc.IsSerializable.ToString()); 
     return 1; 
    } 
} 

Vous pouvez tester la propriété IsSerializable dans votre constructeur et lancer une exception d'exécution dans le cas où quelqu'un enlève [Serializable] inadvertantly. Si vous utilisez des tests unitaires, vous pouvez détecter les problèmes au moment du test.

Questions connexes