So I'm using interfaces more these days. But I am coming across a brick wall this time.
Just for context only let me show you the RESTful WCF contract here that I designed to show you how I'm using IPaymentRequest:
[ServiceContract]
public interface IPaymentService
{
[WebInvoke(Method = "POST", UriTemplate = "/PreAuthorization")]
PreAuthorizeResponse SendTransaction(PreAuthorizeRequest request);
[WebInvoke(Method = "POST", UriTemplate = "/Capture")]
CaptureResponse SendTransaction(CaptureRequest captureRequest);
... and so on
}
The implementation of the Service Contract for example has some methods that look like this:
public PreAuthorizeResponse SendTransaction(PreAuthorizeRequest request)
{
.....
Processor.SetSettings(request);
}
(Note/disclaimer on clean code principals. I have better names for stuff like the name SetSettings() but for privacy I've named stuff more simple such as "SetSettings" and "Process" for this Stack post. In reality I have what kind of processor in its class name so just FYI).
Second, let me make you aware that I have a Processor class that is basically kinda like a utility class to do some things such as send the request fields to an outside REST API. And in this class one example of another method I'm setting up is a SetSettings method that I'll set some stuff based on the type of request that comes in. Mostly, I'm going to get the stuff I need from its Transaction property.
public class Processor
{
private void SetSettings(IPaymentRequest request)
{
var someValue = request.Transaction.SomeProperty1;
...
}
}
Now here's what the IPaymentRequest looks like:
public interface IPaymentRequest
{
string Token { get; set; }
int ClientID { get; set; }
}
Now here are a couple examples of my domain models (the Models my Service Contract expects to be sent in from client requests) that implement IPaymentRequest:
public class PreAuthorizeRequest : IPaymentRequest
{
public string Token { get; set; }
public int ClientID { get; set; }
public int Amount { get; set; }
public PreAuthTransaction Transaction { get; set; }
}
public class CaptureRequest : IPaymentRequest
{
public string Token { get; set; }
public int ClientID { get; set; }
public int BankID { get; set; }
public CaptureTransaction Transaction { get; set; }
}
I'm using IPaymentRequest throughout my WCF service (it's the type that's expected to be sent into my payment service's method contracts) and using these interfaces elsewhere in my service to make some good reuse of methods that these requests can flow through such as SendRequest(IPaymentRequest request), and so on.
Here is the dilema/problem I have:
In methods where I want to reuse the logic for any kind of request that comes in, I end up having to check for what type it is incoming to my methods sometimes in my processor class. So I am having to create a bunch of messy if statements in order to determine and cast the incoming ITransaction in order to start using it in my utility mehtods here.
So lets continue more so I can explain more about my First method SetSettings()
Notice that I need values from the transaction object in the request and to be able to work with properties in that TYPE of request.
Now lets take a look at the CaptureTransaction object for example for a CaptureRequest
public class CaptureTransaction : ITransaction
{
public string Reference { get; set; }
public decimal Amount { get; set; }
public string CurrencyCode { get; set; }
public CreditCard CustomerCreditCard { get; set; }
}
So as you can see, for each Request Type I have a related concrete Transaction Type that implements ITransaction and holds info that the transaction needs to send over to an external API.
Note: All requests WILL always have a transaction (ITransaction) so I thought it'd be therefore a good idea to maybe throw ITransaction in my IPaymentRequest so something like this:
public interface IPaymentRequest
{
string Token { get; set; }
int ClientID { get; set; }
ITransaction Transaction {get; set; }
}
And here is ITransaction. Every request that comes into our service will require a currency now and in the future so this field was a good candidate/reason to use an Interface:
public interface ITransaction
{
string CurrencyCode { get; set; }
}
So adding that to my IPaymentRequest now requires me to change the Property Name in my Custom Types to "Transaction", for example:
public class CaptureRequest : IPaymentRequest
{
public string Token { get; set; }
public int ClientID { get; set; }
public int BankID { get; set; }
public ITransaction Transaction { get; set; }
}
I thought ok fine.
But now if I try to work with Transactions in my utility method, since it's an Interface variable, it has no idea what type of Transaction it is. So I end up having to cast it before I can use it:
private void SetSettings(IPaymentRequest request)
{
ITransaction transaction;
if (request is CaptureRequest)
transaction = request.Transaction as CaptureTransaction;
if (request is PreAuthorizeRequest)
transaction = request.Transaction as PreAuthorizeTransaction;
... etc.
var someValue = request.Transaction.Some1;
...carry on and use SomeProperty1elsewhere in this method for whatever reason
}
IMO it just feels strongly like huge code smell. So obviously I am not doing something right or I don't yet know something about Interfaces that I should know...that allows me to use them better here or without so much casting. And just too much casting IMO is bad, performance-wise.
Maybe this is a good case to use Generics instead of interface parameters in methods I want to create for reuse across different types of Concrete Request types (Capture, PreAuth, Void yada yada)?
The whole point here is I want to be able to specify interface params in some methods to make them DRY (don't repeat yourself) / reusable...and then use the concrete type that came in via polymorphism and work with the request instance.