1

I'm playing around with WCF REST on .NET 4.0, and I ended up wanting to find out if the following idea is somehow possible to implement?

I have a very basic set of POCOs against an EF 4.1 CF project. All of them inherit from a base Entity class (for the sole purpose of defining a PK).

public abstract Entity {
    public int Id { get; set; }
}

Now, for the most part, I'll have separate operations for the CRUD functionality for each of my entities (or aggregates, on larger systems I guess).

e.g.

[ServiceContract]
public class UserService {
    [OperationContract]
    public void Add(User user) {
        // commit to EF
        fooContext.Users.Add(user);
        fooContext.SaveChanges();
    }
}

Now, this is primarily just for convenience, but I was thinking that something like this would be really handy:

[ServiceContract]
public abstract class BaseCrudService<T> where T : Entity {
    [OperationContract]
    public void Add(T entity) {
        // commit to EF via generic methods
        fooContext.Set<T>().Add(entity);
        fooContext.SaveChanges();
    }
}

public class UserService : BaseCrudService<User> {
    // blah
}

... which would theoretically allow me to access that operation via http://<root>/userservice/add and work with it as I would expect to, except that I can't inherit a ServiceContract-decorated class, so there's no hope of automagically cascading functionality down to the endpoints themselves.

I was wondering: is there a way to do this somehow? I know that inheritance (in this manner) won't cut it, but are there other ways to do this? Repeating similar pieces of code across multiple service operations just sounds like something that somebody would have thought of before and fashioned a cleaner modus operandi of implementing.

Richard Neil Ilagan
  • 14,627
  • 5
  • 48
  • 66
  • Does my solution below work for you (from user1039947)? I would be interested to know if you are happy with it – kmp Nov 25 '11 at 06:49

2 Answers2

3

You can use an interface as a service contract so what you can do is the following:

public abstract class BaseCrudService<T> where T : Entity
{        
    public void Add(T entity)
    {
        // commit to EF via generic methods
        fooContext.Set<T>().Add(entity);
        fooContext.SaveChanges();
    }
}

public class UserService : BaseCrudService<User>, IUserService
{
    // No need to put anything in here, just need a constructable class
}

// You would need to create an interface for each service you expose like so
[ServiceContract]
public interface IUserService
{
    [OperationContract]
    void Add(User entity);
}

Do it that way and you do not need to duplicate any code.

For completeness, here is the config:

<system.serviceModel>
  <bindings />
  <services>
    <service name="Demo.UserService">
      <endpoint address=""
                behaviorConfiguration="json"
                binding="webHttpBinding"
                name="jsonEndpoint"
                contract="Demo.IUserService" />
    </service>
  </services>
  <behaviors>
    <endpointBehaviors>
      <behavior name="json">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</system.serviceModel>
kmp
  • 10,535
  • 11
  • 75
  • 125
  • This worked perfectly, with only one change: I also declared the interface as a generic interface (i.e. `interface IUserService where T : Entity`), and inherited the base service and service contract using the same class for the generic type. Thanks! – Richard Neil Ilagan Nov 25 '11 at 08:49
1

AFAIK, using generics on service operations is impossible. :(

You could add a wrapper to your public void Add(T entity) in UserService ... but that would defeat the purpose of your generics-based framework.

Richard Neil Ilagan
  • 14,627
  • 5
  • 48
  • 66