【问题标题】:Create instance with generic parameter使用泛型参数创建实例
【发布时间】:2012-11-06 03:51:35
【问题描述】:

[编辑]

我再次整理我的问题,

参数模型

public class PaymentModel
{   
    ... 
}

public class CCPaymentModel : PaymentModel
{
    ...
}

public class PaypalPaymentModel : PaymentModel
{
    ...
}

public class GooglePaymentModel : PaymentModel
{
    ...
}    

接口类

public interface IPayment<T> where T : PaymentModel
{
    ...
}

模型(从 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>
{...}

控制器(创建实例)

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);
}

[编辑#2]

有了这个,

public interface IPayment {
}

public interface IPayment<T> : IPayment where T : PaymentModel
{
    void MakePayment(string pickno);
    void makeRefund(T refundInfo);
}

我收到一个错误,错误 1“com.WebUI.Models.IPayment”不包含“MakePayment”的定义,并且没有扩展方法“MakePayment”接受“Ecom.WebUI.Models.IPayment”类型的第一个参数可以找到(您是否缺少 using 指令或程序集引用?)

所以,为了避免这个错误,我将 MakePayment 方法移动到上层接口类,

public interface IPayment {
    void MakePayment(string pickno);
}

public interface IPayment<T> : IPayment where T : PaymentModel
{
    void makeRefund(T refundInfo);
}

现在,错误消失了,但是在 makeRefund 的情况下我应该怎么做呢? 因为需要泛型类型参数,所以无法转到上层接口类。

你能帮我多一点吗?

【问题讨论】:

  • 您可能希望有另一个IPayment 接口,而没有IPayment&lt;T&gt; 继承自的泛型。即:public interface IPayment&lt;T&gt; : IPayment where T : PaymentModel.
  • 您将需要此方法通过反射创建泛型类型:msdn.microsoft.com/en-us/library/…
  • 你需要实例化实现 IPayment 的东西。您的示例中没有此类。你不能实例化一个接口。
  • @ChrisSinclair 知道了 - 会有助于看到这些课程。

标签: c# generics interface


【解决方案1】:

您可能希望有另一个 IPayment 接口,而没有 IPayment 继承自的泛型。那就是:

public interface IPayment
{

}

public interface IPayment<T> : IPayment where T : PaymentModel
{

}

编辑:如果您真的不想拥有IPayment 基本接口,那么您必须将它们视为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();
}

但这可能会在以后花费您;无论您将不得不强制转换以使用特定的实现类型。你真的最好使用基本接口。你甚至可以很好地使用它:

public interface IPayment
{
    PaymentModel Payment { get; }
}

因此,您可以参考和使用PaymentModel,而无需知道它实际上是一个GooglePaymentModel

编辑:根据您的评论,您可能有以下内容:

public interface IPayment
{
    void MakePayment(string pickno);
}

public interface IPayment<T> : IPayment where T : PaymentModel
{
    void MakeRefund(T refundInfo);
}

您甚至可以针对PaymentModel 键入非通用MakeRefund 版本,因此您的调用代码可能不在乎它是否为GooglePayment。 (但如果他们通过PayPalPayment 可能会导致其他问题,这取决于您)

编辑:根据你的最新代码,你会想要这样的东西:

public interface IPayment
{

}

public interface IPayment<T> : IPayment where T : PaymentModel
{
    void MakePayment(T paymentInfo);
    void MakeRefund(T paymentInfo);
}

您的控制器/工厂如下所示:

//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
}

您的使用代码某处必须将其转换为已知的支付类型才能使用:

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());

编辑:根据您的最新编辑,这就是您想要的。针对 PaymentModel 驱动您的基本 IPayment 调用。然后在特定的实现中,您可以在运行时进行强制转换或类型检查:

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;
    // ...
    }
}

然后你的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
}

【讨论】:

  • 我现在在 IPayment 中有 2 个方法,我需要把这些方法放在哪个类中? (void MakePayment(string pickno), void makeRefund(TfundInfo))
  • @Expertwannabe 取决于他们是否被强输入PaymentModelMakePayment 可能可以提升为基类,但makeRefund 不会。
  • 感谢您的帮助,但我仍然无法解决问题。请您再次查看我编辑的问题吗?我用更多的代码重写。
  • 我用新的控制器代码再次编辑了我的问题,你能再检查一遍吗?很抱歉打扰你。
  • @Expertwannabe 我添加了另一个编辑。同样从您的代码/错误/屏幕截图中,您需要IPayment&lt;T&gt; 继承自IPayment。请参阅我原始答案中的 very first 代码块。您的IPayment&lt;T&gt;当前继承自IPayment。你需要解决这个问题。
猜你喜欢
  • 1970-01-01
  • 2019-12-17
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
  • 2020-04-03
  • 1970-01-01
  • 2022-11-18
  • 2011-05-19
相关资源
最近更新 更多