C#Generics CoVariance - ContraVariance Conflict

时间:2018-04-24 08:15:42

标签: c# generics covariance contravariance

我遇到了与仿制协方差/逆差异冲突有关的以下问题。

public interface IEmailTemplateInput
{
    List<string> ToEmail { get; set; }
    string Subject { get; set; }
    string FromEmail { get; set; }
}

public interface IEmailCommunicationTemplate<in TInputData> where TInputData : IEmailTemplateInput
{
    void ProcessTemplate(TInputData input);
    Task ProcessTemplateAsync(TInputData input);
}


// Below is the implementation using above interfaces

 public class RiskPeerReviewNotificationTemplate
    : IEmailCommunicationTemplate<RiskPeerReviewNotificationTemplate.Input>

{
    private readonly IEmailService _emailService;
    private readonly ITemplateService _templateService;

    public class Input : IEmailTemplateInput
    {
        public string TenantName { get; set; }
        public string FirstName { get; set; }
        public string CallToActionUrl { get; set; }

    }

    public RiskPeerReviewNotificationTemplate(IEmailService emailService, ITemplateService templateService)
    {
        _emailService = emailService;
        _templateService = templateService;
    }


    protected override Task ProcessAsync(Input input)
    {
      //... Method implementation
    }

}

现在我想注册IEmailCommunicationTemplate并基于输入参数(在本例中为EmailTemplateType),     想要生成不同的实现。

But I run into problems during Autofac registration

 // Register email templates
        iocBuilder.Register<IEmailCommunicationTemplate<IEmailTemplateInput>>((c, p) =>
            {
                var type = p.TypedAs<EmailTemplateType>();
                switch (type)
                {
                    case EmailTemplateType.NewUserNotificationTemplate:
                        return new NewUserNotificationTemplate(c.Resolve<IEmailService>(),
                            c.Resolve<ITemplateService>());
                    case EmailTemplateType.RiskPeerReviewNotificationTemplate:
                        return new RiskPeerReviewNotificationTemplate(c.Resolve<IEmailService>(),
                            c.Resolve<ITemplateService>());
                    default:
                        throw new ArgumentException("Invalid Email Template type");
                }
            })
            .As<IEmailCommunicationTemplate<IEmailTemplateInput>>();

现在显然我不能这样做,因为有反方差。上述注册的实际问题是因为我有效地做了类似的事情     IEmailCommunicationTemplate test2 = new RiskPeerReviewNotificationTemplate(emailService,templateService); 这是不可能的......

  

我无法改变       IEmailCommunicationTemplate其中TInputData:IEmailTemplateInput IEmailCommunicationTemplate其中TInputData:IEmailTemplateInput

because TInputData also comes as parameter in methods (contraVariance nature)...

在stackoverflow上提出的一个解决方案

Generics, Covariance/Contravariance, etc

that would resolve compilation issue : 

1) Have two interfaces 

interface IEmailContravarianceCommunicationTemplate<out TInputData> where TInputData : IEmailTemplateInput

and 

interface IEmailCovarianceCommunicationTemplate<out TInputData> where TInputData : IEmailTemplateInput

2) Have RiskPeerReviewNotificationTemplate implement both.

3) Use interface depending on their context

0 个答案:

没有答案