2010-10-18 2 views
1

J'ai un revendeur hypothétique qui peut fournir certains services; tous les Services sont identiques: ils menacent certaines données IRequest, plus certains IExtraData, et fournissent une réponse IResponse.C# Implémentation de l'interface: faire les bonnes choses

S'il vous plaît lire ce code (travail sur C# 2.0):

public interface IResellerService<in TIn, in TInExtra, out TOut, in TOutExtra> 
    where TIn : IRequest 
    where TInExtra : IExtraData 
    where TOut : IResponse 
    where TOutExtra : IExtraData 
{ 
    #region Properties 
    string Code 
    { 
     get; 
     set; 
    } 

    //Some other simple properties here... 
    #endregion 

    //Some methods there... 
} 

//Need a collection of IResellerServices; using a IList just to have Add facility 
public interface IResellerServices : IList<IResellerService<IRequest, IExtraData, IResponse, IExtraData>> 
{ 
    IResellerService<IRequest, IExtraData, IResponse, IExtraData> Get(string code); 
    void Update(IResellerService<IRequest, IExtraData, IResponse, IExtraData> reseller); 
    void Delete(string code); 
    void Disable(string code); 
} 

public class AvailabilityService : IResellerService<AvailabilityDocumentRequest, AvailabilityInputExtraData, AvailabilityDocumentResponse, AvailabilityOutputExtraData> 
{ 
    //Here the interface implementation; 


    /* 
    NOTE IResellerService declaration 
    AvailabilityDocumentRequest : IRequest 
    AvailabilityInputExtraData : IExtraData 
    AvailabilityDocumentResponse : IResponse 
    AvailabilityOutputExtraData : IExtraData 
    */ 
} 


[Serializable] 
public class Reseller : IReseller 
{ 
    #region Properties 
    public string Code 
    { 
     get; 
     set; 
    } 

    [XmlArray("Services")] 
    [XmlArrayItem("Service")] 
    public IResellerServices Services 
    { get; set; } 

    //Some other simple properties here... 
    #endregion 

    //Some methods there... 
} 

//Just to make me explain... 
void Main() 
{ 
    Reseller res = new Reseller; 
    //Fill reseller properties here... 
    //... 

    AvailabilityService service = new AvailabilityService(); 
    //Fill service properties here... 
    //... 

    //ERROR! 
    res.Add(service); //<-- ERROR! Need to cast my AvailabilityService to IResellerService<IRequest, IExtraData, IResponse, IExtraData> 

    //OK 
    res.Services.Add(service as IResellerService<IRequest, IExtraData, IResponse, IExtraData>); 
} 

Eh bien, probablement me manque certains des concepts de base de l'héritage ou la mise en œuvre de l'interface, mais ce que je fais mal?

J'espère que vous pouvez répondre à mes besoins.

+10

Le code ci-dessus * ne fonctionnera pas en C# 2.0 - il utilise la variance générique, qui n'a été introduite qu'en C# 4.0. –

+0

vous devriez lire le concept de variance dans l'interface générique qui est introduite dans .net 4.0 – TalentTuner

+1

show IReseller.Add ou Reseller.Add déclarations – Grozz

Répondre

3

Je pense que le problème que vous rencontrerez ici, c'est que, bien que toutes les interfaces de lancement soient bonnes et bonnes, si vous avez une interface, vous avez vraiment besoin de pour consommer cette interface. Vous n'avez pas fait cela, vous avez spécialisé un type en implémentant cette interface, mais quels types vont utiliser directement cette interface? Voici un exemple:

public interface IService<TModel> 
{ 
    TModel Get(string id); 
} 

public class MyService : IService<MyModel> 
{ 
    public MyModel Get(string id) 
    { 
    // Work 
    } 
} 

var service = new MyService(); 
var model = service.Get("something"); 

Ci-dessus, bien que je l'ai défini une interface pour un service, je suis dépendant pas vraiment sur ce service dans le code. Je suis toujours dépendant de l'implémentation concrète de IService<TModel>: MyService.

Mon code ne devrait pas se soucier de ce que MyService est, il devrait seulement se soucier qu'il peut supporter les opérations définies par IService<TModel>. Si nous avions refondus ceci:

public class ModelFactory<TModel> 
{ 
    IService<TModel> _service; 

    public ModelFactory(IService<TModel> service) 
    { 
    _service = service; 
    } 

    public TModel Get(string code) 
    { 
    return _service.Get(code); 
    } 

} 

Maintenant, j'ai une classe qui peut consommer mon interface, et me permet de découpler la mise en œuvre loin de mon code:

var factory = new ModelFactory<MyModel>(new MyService()); 
var model = factory.Get("something"); 

En général vous feriez quelque chose avec IoC/DI pour injecter la dépendance, mais j'espère que c'est un exemple clair.

+0

Matthew, votre solution Factory est une bonne solution. Après le déjeuner (ici en Italie il est midi et demi :-)) Je voudrais essayer. Merci! –

Questions connexes