Avoiding type checking when interface method param

2019-08-09 11:51发布

问题:

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.

回答1:

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.



标签: c# oop interface