如何在C# .Net Core中使用反射和工厂设计模式

4

我已经在C# .Net Core中以以下方式实现了工厂方法。我有几个具体产品,比如说Gateway1Gateway2

public interface IGateway
{
    void Test();
}

具体创建者:

public class PaymentFactory
{
    private readonly IPaymentTransactionRepository _paymentTransactionRepository;
    private readonly IPaymentGatewayRepository _paymentGatewayRepository;

    public PaymentFactory(IPaymentTransactionRepository paymentTransactionRepository,
        IPaymentGatewayRepository paymentGatewayRepository)
    {
        _paymentTransactionRepository = paymentTransactionRepository;
        _paymentGatewayRepository = paymentGatewayRepository;
    }

    public IGateway ExecuteCreation(string bank)
    {
        switch (bank)
        {
            case "Gateway1":
                {
                    return new Gateway1(_paymentGatewayRepository);
                }
            case "Gateway2":
                {
                    return new Gateway2(_paymentTransactionRepository, _paymentGatewayRepository);

                }
            default:
                {
                    return null;

                }
        }
    }

}

具体产品:

public class Gateway1 : IGateway
{
    private readonly IPaymentTransactionRepository _paymentTransactionRepository;

    public Gateway1(IPaymentTransactionRepository paymentGatewayRepository)
    {
        _paymentGatewayRepository = paymentGatewayRepository;
    }

    public void Test()
    {
        //code
    }
}

public class Gateway2 : IGateway
{
    private readonly IPaymentTransactionRepository _paymentTransactionRepository;
    private readonly IPaymentGatewayRepository _paymentGatewayRepository;

    public Gateway2(IPaymentTransactionRepository paymentGatewayRepository,
        IPaymentGatewayRepository paymentGatewayRepository)
    {
        _paymentGatewayRepository = paymentGatewayRepository;
        _paymentGatewayRepository = paymentGatewayRepository;
    }

    public void Test()
    {
        //code
    }
}

这段代码正在运行,但我想对它进行两个更改。

1- 如何通过反射实现工厂方法?

2- 如何传入多个参数以创建ConcreteProducts

提前感谢。

2个回答

2

您可以使用以下代码。您需要将PaymentFactory更改如下。 您可以使用IServiceProvider将服务注入到使用它的类的构造函数中。

具体产品名称:

public enum PaymentGatewayEnum
{
    Gateway1 = 1,
    Gateway2 = 2,
}

接下来是PaymentFactory:

public class PaymentFactory
{
    private readonly IServiceProvider _serviceProvider;
    public PaymentFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public IGateway ExecuteCreation(PaymentGatewayEnum bank)
    {
        var services = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
            .Where(x => typeof(IGateway).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
            .FirstOrDefault(x => string.Equals(x.Name, bank.ToString(), StringComparison.CurrentCultureIgnoreCase));

        return Activator.CreateInstance(services, _serviceProvider) as IGateway;
    }

}

然后:

public class Gateway1 : IGateway
{
    private readonly IPaymentTransactionRepository _paymentTransactionRepository;

    public Gateway1(IServiceProvider serviceProvider)
    {
        _paymentTransactionRepository = (IPaymentTransactionRepository)serviceProvider.GetService(typeof(IPaymentTransactionRepository));
    }

    public void Test()
    {
        //code
    }
}

public class Gateway2 : IGateway
{
    private readonly IPaymentTransactionRepository _paymentTransactionRepository;
    private readonly IPaymentGatewayRepository _paymentGatewayRepository;

    public Gateway2(IServiceProvider serviceProvider)
    {
        _paymentTransactionRepository = (IPaymentTransactionRepository)serviceProvider.GetService(typeof(IPaymentTransactionRepository));
        _paymentGatewayRepository = (IPaymentGatewayRepository)serviceProvider.GetService(typeof(IPaymentGatewayRepository));
    }

    public void Test()
    {
        //code
    }
}

0

一种替代Reza Jenabi解决方案的方法是以下内容:

枚举以在网关之间进行选择:

public enum PaymentGatewayType
{
    GATEWAY1,
    GATEWAY2,
}

工厂接口:

public interface IPaymentFactory
{
}

可以注册为单例的工厂:

public class PaymentFactory : IPaymentFactory
{
    private Dictionary<PaymentGatewayType, Func<IGateway>> GatewayTypes 
       = new Dictionary<PaymentGatewayType, Func<IGateway>>();

    public PaymentFactory(IServiceProvider serviceProvider)
    {
        Gateways = Assembly.GetExecutingAssembly().GetTypes()
            .Where(t => typeof(IGateway).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract)
            .Select(t => new Func<IGateway>(() => 
                 ActivatorUtilities.CreateInstance(serviceProvider, t) as IGateway))
            .ToDictionary(f => f().GatewayType);
    }

    public IGateway GetGateway(PaymentGatewayType gatewayType)
    {
        return GatewayTypes[gatewayType]();
    }
}

网关:

public interface IGateway
{
    //The GatewayType property is important as that's what the PaymentFactory uses
    // as a discriminator (see .ToDictionary(f => f().GatewayType);)
    PaymentGatewayType GatewayType{ get; }
    void Test();
}

public class Gateway1 : IGateway
{
    private readonly IPaymentTransactionRepository _paymentTransactionRepository;

    //Here we override the GatewayType property in the interface to set which 
    //gateway this class belongs to
    public override PaymentGatewayType GatewayType => PaymentGatewayType.GATEWAY1;

    public Gateway1(IPaymentTransactionRepository paymentGatewayRepository)
    {
        _paymentGatewayRepository = paymentGatewayRepository;
    }

    public void Test()
    {
        //code
    }
}

public class Gateway2 : IGateway
{
    private readonly IPaymentTransactionRepository _paymentTransactionRepository;
    private readonly IPaymentGatewayRepository _paymentGatewayRepository;

    //Here we override the GatewayType property in the interface to set which 
    //gateway this class belongs to
    public override PaymentGatewayType GatewayType => PaymentGatewayType.GATEWAY2;

    public Gateway2(IPaymentTransactionRepository paymentGatewayRepository,
        IPaymentGatewayRepository paymentGatewayRepository)
    {
        _paymentGatewayRepository = paymentGatewayRepository;
        _paymentGatewayRepository = paymentGatewayRepository;
    }

    public void Test()
    {
        //code
    }
}

然后在调用代码中添加类似以下的内容:

public class GatewayService
{
    private readonly IPaymentFactory _paymentFactory;

    public GatewayService(IPaymentFactory paymentFactory)
    {
        _paymentFactory = paymentFactory;
    }

    public void DoSomething(PaymentGatewayType gatewayType)
    {
        IGateway gateway = _paymentFactory.GetGateway(gatewayType);

        gateway.Test();
    }
}

要添加更多的网关,只需添加一个新的枚举值,例如GATEWAY3,并创建一个继承自IGateway的新的Gateway3类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接