2009-06-01 7 views
5

Comment autoriser mon CookieData à être générique dans le code suivant? Je reçois une erreur de compilation sur la déclaration de ICookieService2.Utilisation de génériques dans les interfaces

public struct CookieData<T> 
{ 
    T Value { get; set; } 
    DateTime Expires { get; set; } 
} 

public interface ICookieService2: IDictionary<string, CookieData<T>> 
{ 
    // ... 
} 

Mon erreur est:

Le type ou le nom namespace 'T' n'a pas pu être trouvée (vous manque une directive à l'aide ou une référence d'assemblage?)

Je suis vouloir ICookieService2 pour y insérer des données génériques. Merci!

Éditer Est-ce que ça ne va pas me bloquer dans un seul T pour la construction de ICookieService2?

Edit 2 Ce que je suis en train de faire est la suivante:

CookieData<int> intCookie = { Value = 27, Expires = DateTime.Now }; 
CookieData<string> stringCookie = { Value = "Bob", Expires = DateTime.Now }; 

CookieService2 cs = new CookieService2(); 
cs.Add(intCookie); 
cs.Add(stringCookie); 

Répondre

7

Il semble que vous avez 3 options ici

Faire ICookieService2 générique

public interface ICookieService2<T> : IDictionary<string, CookieData<T> { 
... 
} 

Créer une base non générique classe pour CookieData et l'utiliser dans l'interface

public interface ICookieData {} 
public class CookieData<T>: ICookieData{} 
public interface ICookieService2 : IDictionary<string, ICookieData> {} 

Choisissez un mise en œuvre concrète

public interface ICookieService : IDictionary<string, CookieData<int>> {} 
4

Vous devez faire ICookieService2 générique ainsi:

public interface ICookieService2<T>: IDictionary<string, CookieData<T>> 
{ 
    // ... 
} 
2

OK, voici ce que vous voulez:

public interface ICookieDataBase 
{ 
    DateTime Expires { get; set; } 
} 

public struct CookieData<T> : ICookieDataBase 
{ 
    public T Value { get; set; } 
    public DateTime Expires { get; set; } 
} 

public class ICookieService : IDictionary<string, ICookieDataBase> 
{ 
    // ... 
} 

public void DoWork() 
{ 
    var intCookie = 
     new CookieData<int> { Value = 27, Expires = DateTime.Now }; 

    var stringCookie = 
     new CookieData<string> { Value = "Bob", Expires = DateTime.Now }; 

    ICookieService cs = GetICookieService(); 
    cs.Add(intCookie); 
    cs.Add(stringCookie); 
} 
0

pas sûr de C#, mais la façon Java serait aussi de déclarer yo ur ICookieService2 pour avoir le paramètre <T>, ou pour spécifier <T> à quelque chose de concret dans CookieData.

+0

ok, voir d'en haut les réponses c'est correct :) – Jorn

1

Je pense que ce que vous voulez est:

public interface ICookieService2<T>: IDictionary<string, CookieData<T>> 
{ 
    // ... 
} 

actuellement ICookieService2 n'est pas générique, donc T est pas défini.

Cela vous permet de créer des classes ou la mise en œuvre ICookieService2<string>ICookieService2<int>, etc.

EDIT: En réponse à votre dernière demande, je pense que cela dépend vraiment exactement ce dont vous avez besoin. Cependant, quelque chose comme ça peut fonctionner pour vous.

public interface ICookieData 
{ 
    object Value {get;} // if you need to be able to set from CookieService, life gets harder, but still doable. 
    DateTime Expires {get;} 
} 

public struct CookieDate<T> : ICookieData 
{ 
    T Value {get;set;} 
    DateTime Expires {get;set;} 

    object ICookieData.Value 
    { 
     get 
     { 
      return Value; 
     } 
    } 
} 

Alors CookieService peut être ou avoir une liste et vous seriez en mesure d'ajouter à la fois CookieData et CookieData. Si vous devez écrire à partir de CookieService, c'est un peu plus compliqué, et peut-être préférable de ne pas utiliser de génériques. Mais si vous avez juste besoin d'être en mesure de récupérer le CookieData, alors cela pourrait fonctionner pour vous.

1

Vous avez besoin d'une interface non générique pour le faire:

public interface ICookieData 
{ 
    // you need this to get the value without knowing it's type 
    object UntypedValue { get; } 
    // whatever you need additionally ... 
    Type DataType { get; } 

    DateTime Expires { get; set; } 
} 

public struct CookieData<T> : ICookieData 
{ 
    // ICookieData implementation 
    public object UntypedValue { get { return Value; } } 
    public Type DataType { get { return typeof(T); } } 
    public DateTime Expires { get; set; } 

    // generic implementation 
    T Value { get; set; } 
} 

public interface ICookieService2: IDictionary<string, ICookieData> 
{ 
    // ... 
} 

CookieData<int> intCookie = { Value = 27, Expires = DateTime.Now }; 
CookieData<string> stringCookie = { Value = "Bob", Expires = DateTime.Now }; 

CookieService2 cs = new CookieService2(); 
cs.Add(intCookie); 
cs.Add(stringCookie); 
0

Si je comprends bien votre question, vous êtes désireux de traiter les types génériques comme ils sont les mêmes, mais dans la mise en œuvre .NET actuelle vous ne pouvez pas le faire.

CookieData < chaîne > ne peut pas être passé en CookieData <int> ils sont en fait différents types, les types génériques ne sont pas liés et ne peut pas être jeté ou passé comme ils sont les mêmes. Créer ICookieService2 en tant que générique ouvert (ce qui signifie ICookieService2 <T>) ne résout pas le problème car vous auriez alors un type ICookieService2 différent pour chaque type différent et tous seraient dans un dictionnaire différent.

Vous pouvez créer une interface ICookieData et l'implémenter dans CookieData <T> et utiliser ICookieData pour stocker les éléments dans le dictionnaire (comme Stefan l'a déjà suggéré).

Vous pouvez faire ce que vous voulez en C# 4.0 (avec quelques restrictions). Il y a un article à ce sujet here jusque-là, vous devez le passer comme un type non-générique qui leur est commun comme une interface ou juste avoir le paramètre valeur être un objet sur le dictionnaire parce que vous allez devoir le cas pour l'utiliser de toute façon si vous utilisez des primitives comme arguments de type.

0

Vous pouvez essayer

public struct CookieData<T> 
    where T : Object 
{ 
    T Value { get; set; } 
    DateTime Expires { get; set; } 
} 

De cette façon, toutes les instances de T seraient forcés d'avoir un type de base de l'objet. (à peu près tout en C# (par exemple int == System.Integer etc.)

Questions connexes