Reputation: 10624
[EDIT]
I organize my question again,
Models for parameter
public class PaymentModel
{
...
}
public class CCPaymentModel : PaymentModel
{
...
}
public class PaypalPaymentModel : PaymentModel
{
...
}
public class GooglePaymentModel : PaymentModel
{
...
}
Interface class
public interface IPayment<T> where T : PaymentModel
{
...
}
Models (get inheritance from IPayment),
public class SagePayment
: IPayment<CreditCardPaymentInfo>
{
public void MakePayment( CreditCardPaymentInfo creditCardPaymentInfo ) {
// ...
}
public void MakeRefund( CreditCardPaymentInfo creditCardPaymentInfo ) {
// ...
}
}
public class GooglePayment
: IPayment<GooglePaymentModel>
{
public void MakePayment( GooglePaymentModel paymentInfo ) {
// ...
}
public void MakeRefund( GooglePaymentModel paymentInfo ) {
// ...
}
}
public class PaypalPayment
: IPayment<PayPalPaymentModel>
{...}
Controller (Create instance)
IPayment<???> paymentProcess; // //Error 1 Using the generic type 'com.WebUI.Models.IPayment<T>' requires 1 type arguments
if (Regex.IsMatch(paytype, "^Credit Card"))
{
paymentProcess = new SagePayment(); // it need CCPaymentModel type parameter
}
else if (Regex.IsMatch(paytype, "^PayPal"))
{
paymentProcess = new PayPalPayment(); // it need PaypalPaymentModel type parameter
}
else if (Regex.IsMatch(paytype, "^Google"))
{
paymentProcess = new GooglePayment(); // it need GooglePaymentModel type parameter
}
[EDIT]
public void Charge(string paytype,orderNo){
IPayment<???> paymentProcess; // //Error 1 Using the generic type 'com.WebUI.Models.IPayment<T>' requires 1 type arguments
Object payinfo;
if (Regex.IsMatch(paytype, "^Credit Card"))
{
paymentProcess = new SagePayment(); // <== Error, Can not casting
payinfo = getPaymentInfo(paytype, orderNo); // it return CCPaymentModel type object
}
else if (Regex.IsMatch(paytype, "^PayPal"))
{
paymentProcess = new PayPalPayment();
payinfo = getPaymentInfo(paytype, orderNo); // it return PaypalPaymentModel type object
}
else if (Regex.IsMatch(paytype, "^Google"))
{
paymentProcess = new GooglePayment(); // it return GooglePaymentModel type object
payinfo = getPaymentInfo(paytype, orderNo);
}
paymentProcess.MakePayment(payinfo);
}
[EDIT #2]
With this,
public interface IPayment {
}
public interface IPayment<T> : IPayment where T : PaymentModel
{
void MakePayment(string pickno);
void makeRefund(T refundInfo);
}
I got an error, Error 1 'com.WebUI.Models.IPayment' does not contain a definition for 'MakePayment' and no extension method 'MakePayment' accepting a first argument of type 'Ecom.WebUI.Models.IPayment' could be found (are you missing a using directive or an assembly reference?)
So, to avoid that error, I move MakePayment method to upper interface class,
public interface IPayment {
void MakePayment(string pickno);
}
public interface IPayment<T> : IPayment where T : PaymentModel
{
void makeRefund(T refundInfo);
}
Now, the error is gone, BUT how should I do in makeRefund case? I can not move to upper interface class because I need generic type parameter.
Could you help me a little more please?
Upvotes: 0
Views: 292
Reputation: 23218
You would want to have another IPayment interface without the generics from which IPayment inherits from. That is:
public interface IPayment
{
}
public interface IPayment<T> : IPayment where T : PaymentModel
{
}
EDIT: If you really don't want to have an IPayment
base interface, then you'd have to treat them as type object
:
object paymentProcess;
if (Regex.IsMatch(paytype, "^Credit Card"))
{
paymentProcess = new SagePayment();
}
else if (Regex.IsMatch(paytype, "^PayPal"))
{
paymentProcess = new PayPalPayment();
}
else if (Regex.IsMatch(paytype, "^Google"))
{
paymentProcess = new GooglePayment();
}
But that might cost you later; regardless you're going to have to cast to work with the specific implementation types. You're really best using a base interface. You may even use it in a nice way:
public interface IPayment
{
PaymentModel Payment { get; }
}
So you can reference and use the PaymentModel
without knowing that it's actually a GooglePaymentModel
specifically.
EDIT: Based on your comment, you might have something like:
public interface IPayment
{
void MakePayment(string pickno);
}
public interface IPayment<T> : IPayment where T : PaymentModel
{
void MakeRefund(T refundInfo);
}
You could even have a non-generic MakeRefund
version typed against PaymentModel
so your calling code might not care if it's a GooglePayment
or not. (but that could cause other issues if they pass a PayPalPayment
, so that's up to you)
EDIT: Based on your latest code, you'll want something like this:
public interface IPayment
{
}
public interface IPayment<T> : IPayment where T : PaymentModel
{
void MakePayment(T paymentInfo);
void MakeRefund(T paymentInfo);
}
Your controller/factory would look like:
//not sure on the exact signature since you didn't provide it
public IPayment CreatePayment(string paytype)
{
IPayment paymentProcess = null;
if (Regex.IsMatch(paytype, "^Credit Card"))
{
paymentProcess = new SagePayment();
}
else if (Regex.IsMatch(paytype, "^PayPal"))
{
paymentProcess = new PayPalPayment();
}
else if (Regex.IsMatch(paytype, "^Google"))
{
paymentProcess = new GooglePayment();
}
return paymentProcess
}
Your usage code would somewhere have to cast it to the known payment type to use:
IPayment untypedPayment = Factory.CreatePayment("PayPal");
IPayment<PayPalPaymentModel> typedPayment = (IPayment<PayPalPaymentModel>)untypedPayment;
typedPayment.MakePayment(new PayPalPaymentModel());
//or alternatively
IPayment untypedPayment = Factory.CreatePayment("PayPal");
PayPalPayment typedPayment = (PayPalPayment)untypedPayment;
typedPayment.MakeRefund(new PayPalPaymentModel());
EDIT: Based on your latest edits, this is what you want. Drive your base IPayment calls against a PaymentModel. Then in the specific implementations you can cast or type-check at runtime:
public interface IPayment
{
void MakePayment(PaymentModel paymentInfo);
void MakeRefund(PaymentModel paymentInfo);
}
public interface IPayment<T> : IPayment where T : PaymentModel
{
}
public class GooglePayment
: IPayment<GooglePaymentModel>
{
public void MakePayment(PaymentModel paymentInfo) {
GooglePaymentModel googlePayment = (GooglePaymentModel)paymentInfo;
// ...
}
public void MakeRefund(PaymentModel paymentInfo) {
GooglePaymentModel googlePayment = (GooglePaymentModel)paymentInfo;
// ...
}
}
Then your Controller
:
public void Charge(string paytype,orderNo){
IPayment paymentProcess = null;
PaymentModel payinfo = null;
if (Regex.IsMatch(paytype, "^Credit Card"))
{
paymentProcess = new SagePayment();
payinfo = getPaymentInfo(paytype, orderNo);
}
else if (Regex.IsMatch(paytype, "^PayPal"))
{
paymentProcess = new PayPalPayment();
payinfo = getPaymentInfo(paytype, orderNo);
}
else if (Regex.IsMatch(paytype, "^Google"))
{
paymentProcess = new GooglePayment();
payinfo = getPaymentInfo(paytype, orderNo);
}
paymentProcess.MakePayment(payinfo);
}
public PaymentModel getPaymentInfo(string paytype,orderNo)
{
//return some payment model
}
Upvotes: 6