I have two interfaces, one with and one without generic type parameters. The non-generic interface is used internally so that I can store instances of the generic interface in a collection. All would be well except for the fact that C# does not generate method signatures based on the return type. I have a method in each interface called GetItems. One returns an IList the other an IList<T>. Since I cannot give them both the same name I need to come up with two different names that both convey what they do. Here are the interfaces:
public interface IBatchProcessingStorage {
void Enqueue(object o);
void Enqueue(IEnumerable items);
void Dequeue(object o);
void Dequeue(IEnumerable items);
IList GetItems(int maxItems);
}
public interface IBatchProcessingStorage<T> : IBatchProcessingStorage {
void Enqueue(T item);
void Enqueue(IEnumerable<T> item);
void Dequeue(T item);
void Dequeue(IEnumerable<T> item);
IList<T> GetItems(int maxItems);
}
There is a task that runs every so often that will get items from the batch processing store, pass them to an external resource, and if they are processed by the external resource then they are removed from the store. The task needs the non-generic interface, that is the only reason it exists. I have created an abstract class that implements both, and redirects the calls in the non-generic interface to the generic ones and the generic ones are abstract like so:
public abstract class BatchProcessingStorage<T>
: IBatchProcessingStorage<T>
, IBatchProcessingStorage {
void IBatchProcessingStorage.Enqueue(object o) { Enqueue((T)o); }
void IBatchProcessingStorage.Enqueue(IEnumerable items) {
Enqueue((IEnumerable<T>)items); }
void IBatchProcessingStorage.Dequeue(object o) {
Dequeue((T)o); }
void IBatchProcessingStorage.Dequeue(IEnumerable items) {
Dequeue((IEnumerable<T>)items); }
IList IBatchProcessingStorage.GetItems(int maxItems) {
return this.GetItems(maxItems).ToArray(); }
public abstract void Enqueue(T item);
public abstract void Enqueue(IEnumerable<T> item);
public abstract void Dequeue(T item);
public abstract void Dequeue(IEnumerable<T> item);
public abstract IList<T> GetItems(int maxItems);
}
This is supposed to be the class that customers will inherit from, but I'm not going to force them into our inheritance hierarchy. So they may have to implement both interfaces. This is the reason for my great concern about the names. I don't want our API to have crap method names. So, what should I call GetItems in each class that conveys meaning without looking like I'm working around language limitations?
Update:
For those of you who think I am over analyzing this: We have learned a lot about our public API over the past 5 years. I have one chance to get this new one right. After that we are stuck with what is released. This is not your average internal software application. It is a software platform that is very extensible. It is used by some of the most well known companies in the world. It is going to be very hard for them to honestly get on stage at our conferences and tout the usefulness of our software platform, if It has a crappy API. This is not overly complex, or overly abstract. It is designed to serve a specific business need. Our customers are going to need this, better yet, they already do through a very poorly named, and overly complex API that makes you jump through hoops to get things done (hindsight is always 20/20).