Coffeehouse Thread

11 posts

Forum Read Only

This forum has been made read only by the site admins. No new threads or comments can be added.

C# partial classes implementing multiple interfaces.

Back to Forum: Coffeehouse
  • User profile image
    Lee_Dale

    So I am building out a largish WCF REST service and wanted to break down my code by splitting out logical implementation code into different code files.

    I have three main logical separation: "Categories", "Topics" and "Posts".  

    Heres the thing, I only wanted to specify one SVC file in my web.config <service> node base address and then just configure an endpoint for each logical element.

    I started by creating an Interface for each element, Categories, Topics and Posts then specifying an endpoint for each element referring to the relevant interface.

    The problem with one .svc file is that you can only point it to a single class type.

    Anyway my thought was to break out the implementation code for each element into a partial class and have each declaration of that partial class implement the relevant interface.  My reckoning was that when the compiler pulls together each partial class declaration it would treat it like a single class declaration implementing three interfaces.

    Instead the compiler complained that I can't have multiple base classes in a partial class?  I don't see why this isn't possible, can anyone explain why this might be?

    So to clarify in C# I can have the following:

    public class InsiderSpecialsWebService :    IInsiderSpecialsCategoryWebService,
                                                    IInsiderSpecialsTopicWebService,
                                                    IInsiderSpecialsPostWebService

    But I can't have

    public partial class InsiderSpecialsWebService : IInsiderSpecialsCategoryWebService
    
    public partial class InsiderSpecialsWebService : IInsiderSpecialsTopicWebService
    
    public partial class InsiderSpecialsWebService : IInsiderSpecialsPostWebService

     

    I suspect it's the way the compiler pulls together the partial class files, but I don't see why this isn't technically possible.

    I got around this by creating a Repository class that does the grunt work for each logical element and just calling the relevant repository class method from each web service method.  I think it's still nicer than having multiple services configured and hence multiple.svc files or lumping all your implementation code into one large class.

  • User profile image
    Blue Ink

    What version of C# are you using? On my machine, with C# 4, the following code compiles just fine:

     

    public interface IFoo { }
    public interface IBar { }

     

    public partial class Test : IFoo { }
    public partial class Test : IBar { }

     

    I used a reduced test case here, but I don't seem to get any error even when the interfaces actually expose something or when the partial class is spread over multiple source files.

    EDIT: this has been specifically allowed also by version 3 of the C# language specifications:

    10.2.5 Base interfaces

    The set of base interfaces for a type declared in multiple parts is the union of the base interfaces specified on each part. A particular base interface may only be named once on each part, but it is permitted for multiple parts to name the same base interface(s). There must only be one implementation of the members of any given base interface.

     

  • User profile image
    vesuvius

    Not it is not. The number 1 rule (of many) in WCF is that you code against the service contract
    i.e. interface and not interfaces.

    If you look in the web.config you will find behaviors and so on for the class, and the contract, either IInsiderSpecialsCategoryWebServiceIInsiderSpecialsTopicWebService
    or IInsiderSpecialsPostWebService

    If you want the seperation then it is more logical to have a .svc file for each InsiderSpecial. A perfect illustration of this is shown in the WCF ASP.NET roles services where the devide the security, authentication and roles into seperate services. It means
    that I can choose to consume just the authentication piece if I only need that (which I did in 1 scenario). If these categories blow up across time, you can then move them [services] to seperate servers for performance. If this is too much hassle, then add
    all the DataContracts into the one .svc

  • User profile image
    vesuvius

    @Blue Ink: Its not about the language it is about service orientation. WCF is not object oriented at all.

  • User profile image
    JPeless

    I have two different service contracts (via separate public interfaces) exposed in the same WCF service, but they are implemented in the same class, not partial classes.  I do it because I want some of the methods exposed via REST (POX/JSON endpoints) and the others to remain SOAP only.

  • User profile image
    PerfectPhase

    @vesuvius:  The SVC file represents a ServiceHost, which can implement multiple ServiceContracts, it's the endpoints that define the contract
    you actually conect to.  So there is no problem having 1 svc file that implements 3 ServiceContracts.  To the outside world it all looks the same.

  • User profile image
    vesuvius

    @PerfectPhase:Yes, but, if you go for three separate ServiceContracts then you need separate 3 endpoints configuring, on all your client machines. This flexibility is there for when you need to use different WCF bindings. You can easily get the seperation by using DataContracts and the same service contract, that way, the seperation is truly invisible from the calling clients as they connnect to the same endpoint.

    I would however, still consider the SoC on the service level for future flexibility (or is that YAGNI). It's your choice.

  • User profile image
    Lee_Dale

    @PerfectPhase:Yes this is right the service is a whole encompassing "Service" and the endpoints are specific contracts that the client consumes.

    i.e. I expose one endpoint at 

    http://myserver/myservice.svc/Categories

    another at

    http://myserver/myservice.svc/Topics

    and so on.

    Each endpoint has an interface to specify what methods I can call on that service.  Problem with WCF is that it forces you to either use multiple SVC files which looks messy and seems overkill or lump all implementation code into one class.

    I got around it by separating the implementation code into different Repository classes and just use the SVC referenced service class to wire up the method calls to the relevant Repository classes.

    The consumer may only want to work with categories. It's more of a way to separate up the implementation. 

    I'm targeting 3.5 framework and it definitely threw up an error stateting that I can't inherit from multiple base types even though I was implementing an interface?

  • User profile image
    Lee_Dale

    You know what, after refactoring a bit and trying this again it now works!

    You can implement multiple interfaces in seperate partial classes, the error I was getting must of been something specific to WCF. Hmmm no idea why this didn't work before.

    In fact its quite a neat way to break up the implementation code for a service I think.

  • User profile image
    ScanIAm

    Conversation I've actually had:

    Me: So, the interface is broken up into multiple parts based on the functionality that is expected.  The class that implements the interface will implement all the interface functionality based on what it can provide.  The interfaces will be used by various parts of the code based on what they expect the interface to provide.

    Them: That's complicated.  Why can't we just name the methods appropriately.

    Me: I cannot tell you how much I want to bury you in a shallow grave.

  • User profile image
    ScanIAm

    My point being: most of the coolest language/interpreter stuff that is available is completely lost on vast majority of people who actually end up having to support it.  I expect it will be another generation before .Net 2.0 features will be readily accepted as normal.

Conversation locked

This conversation has been locked by the site admins. No new comments can be made.