C# Использование обобщений и делегатов в заводском шаблоне - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь создать фабрику, где я могу возвращать тип класса на основе типа класса, переданного в фабрику. На основе этого я затем вызываю метод для возвращенного класса со связанной, но отдельной подписью. Я пытаюсь использовать делегат для подписи метода, но получаю ошибки компиляции. См. Следующие фрагменты кода:

Политики:

public interface IPolicy
{
       
        Guid Id { get; }

        TypeEnum NetworkType { get; }

}

public class PPOPolicy : IPolicy
{
  // PPO specific properties...
}

public class HMOPolicy : IPolicy
{
  // HMO specific properties...
}

Калькуляторы, требующие определенного типа c IPolicy:

public static class PpoCalculator
{
  public static bool TryBuildEstimate(Treatment treatment, PPOPolicy policy,
            out InsurancePolicyEstimate estimate
        )
        {
         // implementation...
        }
}

public static class HmoCalculator
{
  public static bool TryBuildEstimate(Treatment treatment, HMOPolicy policy,
            out InsurancePolicyEstimate estimate
        )
        {
         // implementation...
        }
}

Телефонный код:

public static class BenefitEstimator
{
public static IEnumerable<InsurancePolicyEstimate> EstimateBenefit(Treatment treatment,
          IReadOnlyList<IPolicy> policies
        )
        {
         var primaryPolicy = policies.First();
         var calculated = Calculate(primaryPolicy, treatment, out var primaryEstimate);
        }

        private static bool Calculate(IPolicy policy, Treatment treatment, out InsurancePolicyEstimate estimate)
        {
            switch (policy)
            {
                case PPOPolicy ppoPolicy:
                    return CalculatorFactory.GetCalculator(ppoPolicy).Invoke(treatment, ppoPolicy, out estimate);
                case HMOPolicy hmoPolicy:
                    return CalculatorFactory.GetCalculator(hmoPolicy).Invoke(treatment, hmoPolicy, out estimate);
                default:
                    throw new ArgumentOutOfRangeException(nameof(policy));
            }
        
}

Это фабрика:

 public static class CalculatorFactory
    {
        public static TryBuildEstimate GetCalculator(IPolicy policy)
        {
            switch (policy)
            {
                case TreatmentInsurancePolicy treatmentInsurancePolicy:
                    return PpoCalculator.TryBuildEstimate;
                case DhmoInsurancePolicy dhmoInsurancePolicy:
                    return HmoCalculator.TryBuildEstimate;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
    }

Это мой делегат:

public delegate bool TryBuildEstimate(Treatment treatment, IPolicy policy, out InsurancePolicyEstimate estimate);

Я пробовал сделать делегата generi c like TryBuildEstimate<in T>(Treatment treatment, T policy, out InsurancePolicyEstimate estimate) where T : IPolicy но тогда подписи не совпадают с таковыми в калькуляторе.

Есть ли способ заставить эту работу работать или способ лучше структурировать весь этот сценарий? В конечном итоге я пытаюсь создать класс оценщика, который может получить любой тип калькулятора в зависимости от типа политики и вернуть подпись оценки bool / out.

...