简体   繁体   English

如何在C#.Net core的工厂设计模式中使用Reflection

[英]How to use Reflection in factory design patterns in C# .Net core

I've implementing the Factory Method in c#.Net core in the following way.I have several concrete products let's say Gateway1 and Gateway2我通过以下方式在 c#.Net 核心中实现了工厂方法。我有几个具体的产品,比如Gateway1Gateway2

public interface IGateway
{
    void Test();
}

ConcreteCreator:具体创建者:

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;

                }
        }
    }

}

ConcreteProducts:具体产品:

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

This code is running but I want to make two changes to it.此代码正在运行,但我想对其进行两处更改。

1- How to implementing the Factory Method by Reflection? 1- 如何通过反射实现工厂方法?

2- How to pass in multiple parameters to Create ConcreteProducts ? 2-如何将多个参数传递给 Create ConcreteProducts

Thanks in advance.提前致谢。

you can use bellow code.You need to change the PaymentFactory as follows.您可以使用波纹管代码。您需要按如下方式更改PaymentFactory you can user IServiceProvider Injection of the service into the constructor of the class where it's used.您可以使用IServiceProvider将服务注入到使用它的类的构造函数中。

ConcreteProducts Names:混凝土产品名称:

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

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

}

and then:进而:

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

An alternative to Reza Jenabi's solution is the following: Reza Jenabi 解决方案的替代方案如下:

Enum to select between gateways:在网关之间枚举到 select:

public enum PaymentGatewayType
{
    GATEWAY1,
    GATEWAY2,
}

The factory interface:工厂界面:

public interface IPaymentFactory
{
}

The factory, which can be registered as a singleton:工厂,可注册为singleton:

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

The gateways:网关:

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

Then in the calling code something like the following:然后在调用代码中如下所示:

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

To add more Gateways simply add a new enum Value, eg GATEWAY3 and create a new Gateway3 class that inherits from IGateway.要添加更多网关,只需添加一个新的枚举值,例如 GATEWAY3,并创建一个继承自 IGateway 的新网关 3 class。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM