Reputation: 266
My interface looks like this:
public interface UserHandler
{
CheckUsernameResponse CheckUsername(CheckUsernameRequest request);
}
The request and response types in the signature are abstract classes, giving a usage of something like:
var fooHandler = new FooUserHandler();
var fooResponse = fooHandler.CheckUsername( new FooRequest { id = 1, FooProperty = "abc" });
or
var barHandler = new BarUserHandler();
var barResponse = barHandler.CheckUserName( new BarRequest { id = 2, BarProperty = true });
What I'm ultimately trying to do is have the ability to have multiple UserHandler implementations, each with their own versions of the request/response types with different properties but having a common base type. I'm doing this to avoid having to make changes to a consuming WCF service in the event that the external user provider changes and a new provider needs different properties in the method call.
Bearing in mind it's possible to pass any type that inherits from the abstract class, i.e. I can pass a BarRequest into a FooHandler, how can I ensure that only the correct/expected types are passed as parameters in the without resorting to:
public CheckUsernameResponse CheckUsername(CheckUsernameRequest request)
if (request.GetType() != typeOf(FooRequest))
throw new ArgumentException("Wrong type!");
var fooRequest = request as FooRequest;
This feels wrong so I'd appreciate any feedback into the specific question and the approach in general.
What I really want is a method signature of:
public FooResponse CheckUsername(FooRequest request)
but if I do that I'm not implementing the interface.
Upvotes: 1
Views: 128
Reputation: 156928
In my opinion, the interface should use generics, so you can rely on the implementation of the interface.
I would suggest something like this:
public interface UserHandler<TRequest, TResponse> where TRequest : CheckUsernameRequest
where TResponse : CheckUsernameResponse
{ }
Then FooHandler
would become:
public class FooHandler : UserHandler<FooRequest, FooResponse>
{ }
And now you are all set, you don't have to check types any more. You are compiler safe.
Upvotes: 2