4

I have the following interface called IAccountService. I also have exactly the same interfaces for Product and Package etc.

public interface IAccountService { void AddOrUpdate(Account account); void Delete(Account account); bool DoesTableExist(); Account Get(Account account); Account Get(string pk, string rk); IEnumerable<Account> Get(); IEnumerable<Account> Get(string pk); string GetOptions(string pk, string rk); IEnumerable<AccountDetail> ShowDetails(ref string runTime); IEnumerable<AccountSummary> ShowSummary(ref string runTime); void ValidateNoDuplicate(Account account); void ValidateNoProducts(Account account); } 

I created some generic methods but I am wondering can I also create a generic interface. If so then how would I call it and how could I change the above to make it generic. Presently I use this interface as follows:

public class AccountService : BaseService, IAccountService 

Update 1

Thanks for all the suggestions. The one thing I still have a problem with is AccountDetail and AccountSummary classes. I am thinking maybe these should be sub classes. But how then can I handle the naming of those? I would have to take the class name, append Detail and then use that in the interface. IS that possible?

Update 2

Here's an example of the detail and summary classes:

public class AccountDetail { public string Title { get; set; } public string Product { get; set; } } public class AccountSummary { public string Title { get; set; } public Int32? ProductCount { get; set; } public string PartitionKey{ get; set; } public string RowKey { get; set; } public DateTime? Modified { get; set; } public string ModifiedBy { get; set; } } 

The above classes are used for reporting. I am thinking that they probably should not be part of the model repository. Maybe they should be in another place.

Regarding the ref comments. The ref is there because in my controller I call the following method:

_account.ShowDetails(ref runTime); 

The output of ShowDetails is a list of details and the runTime reference is updated with the time that it takes to run the report.

2
  • 1
    Those parameters probably should not be ref. Commented Dec 20, 2011 at 14:20
  • Re: Update: No, that's not possible. You need to take one of the existing approaches in the answers. Commented Dec 20, 2011 at 14:40

7 Answers 7

5

You could always do:

public interface IService<T> { bool TableExists { get }; void AddOrUpdate(T item); void Delete(T item); T Get(T item); T Get(string pk, string rk); // etc } public class AccountService : BaseService, IService<Account> 

In the case of the Detail/Summary methods, I would break them out into a separate location (probably some sort of mapper class).

Sign up to request clarification or add additional context in comments.

2 Comments

But how can I name the details? See my comments to original question. Thanks.
@SamanthaJ - What do the detail/summary classes have that the regular class doesn't? Not sure what those classes add at this point. Knowing that would help suggest a design.
4

You can make a generic interface the same way you make a generic class:

public interface IRepository<T> { void AddOrUpdate(T item); bool TableExists { get; } IEnumerable<T> All { get; } ... IEnumerable<Detail<T>> GetDetails(string runTime); ... } 

1 Comment

+1 as you were the only person who dealt with the AccountSummary and AccountDetail issue when I posted this comment
2

This should work for you:

 public interface IService<T, TDetail, TSummary> { void AddOrUpdate(T account); void Delete(T account); bool DoesTableExist(); T Get(T account); T Get(string pk, string rk); IEnumerable<T> Get(); IEnumerable<T> Get(string pk); string GetOptions(string pk, string rk); IEnumerable<TDetail> ShowDetails(ref string runTime); IEnumerable<TSummary> ShowSummary(ref string runTime); void ValidateNoDuplicate(T account); void ValidateNoProducts(T account); } public class AccountService : BaseService, IService<Account, AccountDetail, AccountSummary> public class ProductService : BaseService, IService<Product, ProductDetail, ProductSummary> public class PackageService : BaseService, IService<Package, PackageDetail, PackageSummary> 

Note that you would need 3 types, or have a seperate IAccountService interface that handles the summary and detail methods itself.

Comments

1

Something like this?

public interface IService<T, TDetail, TSummary> { void AddOrUpdate(T entity); void Delete(T entity); bool DoesTableExist(); T Get(T entity); T Get(string pk, string rk); IEnumerable<T> Get(); IEnumerable<T> Get(string pk); string GetOptions(string pk, string rk); IEnumerable<TDetail> ShowDetails(ref string runTime); IEnumerable<TSummary> ShowSummary(ref string runTime); void ValidateNoDuplicate(T entity); void ValidateNoProducts(T entity); } 

A few things to note:

  1. There appeared to be three distinct types to be generalized, so there are three corresponding type parameters. If the latter two aren't correct, go ahead and update or let me know and I can help with that.
  2. I renamed parameters to "entity" as a more generic term. You can choose whatever name makes sense to you.
  3. Are the last two method names generic enough for this? ValidateNoProducts seems suspect to me if it also exists on the Product version of this interface.

All in all, while it's possible to make a single generic interface, one important question you need to ask yourself is if this is indeed the right abstraction. Some of these methods might be intuitively more type-specific and belong on a different type of service.

To that end, you can create an IService<> with most of these methods and then have your AccountService and other services which implement it also add methods of their own. That would seem like a more viable abstraction, as opposed to trying to fit a square peg into a round hole with incorrect abstractions.

Comments

1
public interface IService<T> { void AddOrUpdate(T entity); void Delete(T entity); bool DoesTableExist(); T Get(T entity); T Get(string pk, string rk); IEnumerable<T> Get(); IEnumerable<T> Get(string pk); string GetOptions(string pk, string rk); IEnumerable<AccountDetail> ShowDetails(ref string runTime); // you will need to redisign this part IEnumerable<AccountSummary> ShowSummary(ref string runTime); //same for this method void ValidateNoDuplicate(T account); void ValidateNoProducts(T account); } 

and use it like this:

public class AccountService : BaseService, IService<Account> 

Comments

1
public interface IAccountService<T> { ... SomeDataType<T> SomeMethod(...); ... } 

Comments

1

You could define it like so:

public interface IService<T> { void AddOrUpdate(T entity); T Get(T entity); // etc } 

And use it like so:

public class AccountService : IService<Account> { void AddOrUpdate(Account entity); Account Get(Account entity); // etc } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.