C# 只让抽象类知道其继承者
我正在为我的网站制作一个支付系统。用户可以从多个支付提供商中选择一个进行支付,但所有支付提供商的行为都应相同。我想这样来表现这种行为:C# 只让抽象类知道其继承者,c#,asp.net,C#,Asp.net,我正在为我的网站制作一个支付系统。用户可以从多个支付提供商中选择一个进行支付,但所有支付提供商的行为都应相同。我想这样来表现这种行为: public abstract class PaymentProvider { private static var methods = Dictionary<String,PaymentProvider> { {"paypal",new PaymentProviderPaypal()}, {"worl
public abstract class PaymentProvider {
private static var methods = Dictionary<String,PaymentProvider>
{
{"paypal",new PaymentProviderPaypal()},
{"worldpay",new PaymentProviderWorldpay()}
}
public static Dictionary<String,PaymentProvider> AllPaymentProviders
{
get {return methods;}
}
public abstract pay();
}
public class PaymentProviderPaypal : PaymentProvider {
public override pay() {
}
}
public class PaymentProviderWorldpay : PaymentProvider {
public override pay() {
}
}
您应该通过编写PaymentProvider.AllPaymentProviders[key].pay来使用它。其思想是,使用此类的函数不需要知道底层支付提供者是如何实现的,它们只需要知道密钥
但是,目前,如果您可以访问PaymentProvider类,那么您也可以访问继承类。可以实例化继承类的新副本,并以意外的方式使用它们。我想封装继承类,以便只有抽象PaymentProvider知道它们
我该怎么做?不同的保护级别(如protected)在这里不起作用-在Java中,protected意味着只有命名空间中的其他类可以使用该类,但在C中,它意味着其他一些东西
我的想法对吗?或者我应该使用不同的方法吗?我想到了几个选项: 将其与客户机代码放在一个单独的程序集中,并将实现抽象化 将实现作为私有嵌套类放在PaymentProvider类中。您仍然可以通过使PaymentProvider成为分部类来分离源代码-每个实现使用一个源文件 如果您不介意在程序集方面将客户机与实现分离,那么第一个选项可能是最干净的 请注意,在Jamiec的答案提出更改后,这两个选项仍然有效-可见性部分与继承部分有些正交
顺便说一句,我希望这种方法真的被称为付费而不是付费:你的继承权有点不可靠,我很想用一种类似但截然不同的方式来做
public interface IPaymentProvider
{
void Pay()
}
// Implementations of IPaymentProvider for PaypalPaymentProvider & WorldpayPaymentProvider
public static class PaymentHelper
{
private static var providers = Dictionary<String,IPaymentProvider>
{
{"paypal",new PaymentProviderPaypal()},
{"worldpay",new PaymentProviderWorldpay()}
}
public static void Pay(string provider)
{
if(!providers.Containskey(provider))
throw new InvalidOperationException("Invalid provider: " + provider);
providers[provider].Pay();
}
}
这不是问题的答案:在.NET internal中,允许访问当前程序集中的所有名称空间,受保护的名称空间仅可供继承者访问。依靠用户知道使用哪个键传递给AllPaymentProviders,而不是公开类型,还有什么好处?@Jamiec我在MSDN上看到了这一点。但是,该网站是visual studio下的“网站”项目,这与程序集有关,因此我不想在发生意外情况时使用“内部”。也没有答案:即使在Java中,受保护的内容更多地与继承有关,而不是包。@StevenJeuris继承者可以在其构造函数中有不同的设置,例如为提供者打开测试事务,以及更改ID/密码/设置。我希望最终在一个配置文件中的一个地方初始化所有这些文件,而不是让人们能够访问它们,以按照自己的意愿实例化它们。我可以记录下哪些密钥是有效的,这样用户就知道该调用哪个密钥了。谢谢您的回答。我想我同意你的第二个建议。目前网站的结构不适合将支付代码放在不同的程序集中,我计划最终解决这个问题。为什么使用接口比使用抽象类更好?它是否使它更易于维护/更快?实际上没有区别-使用抽象类的唯一原因是如果您有一些基本实现-我使用接口进行演示。
public interface IPaymentProvider
{
void Pay(double amount);
}
public static void Pay(string provider, double amount)
{
if(!providers.Containskey(provider))
throw new InvalidOperationException("Invalid provider: " + provider);
providers[provider].Pay(amount);
}