C# 是否可以基于枚举输入返回泛型类?

C# 是否可以基于枚举输入返回泛型类?,c#,generics,enums,C#,Generics,Enums,我正在编写一个小的电子邮件模板引擎,使用Razor语法填充令牌。我有几种电子邮件类型: public enum EmailType{欢迎,提醒} 这些类型具有相应的模板和模型,因此,例如欢迎电子邮件具有一个模板: 欢迎,@Model.Name 以及相应的模型: public类WelcomeModel{public string Name{get;set;} 现在我想创建一个方法,该方法将强制为给定的枚举创建正确的模型,我可以想象如下: public ITemplate GenerateTe

我正在编写一个小的电子邮件模板引擎,使用Razor语法填充令牌。我有几种电子邮件类型:

public enum EmailType{欢迎,提醒}
这些类型具有相应的模板和模型,因此,例如
欢迎
电子邮件具有一个模板:

欢迎,@Model.Name

以及相应的模型:

public类WelcomeModel{public string Name{get;set;}
现在我想创建一个方法,该方法将强制为给定的枚举创建正确的模型,我可以想象如下:

public ITemplate GenerateTemplate(EmailType EmailType)
{
交换机(电子邮件类型)
{
案例电子邮件类型。欢迎:
返回新的EmailTemplate();
案例电子邮件类型。提醒:
返回新的EmailTemplate();
// ...
}
其中
EmailTemplate:ITemplate
,这样我就可以链接方法:

引擎
.GenerateTemplate(EmailType.Welcome)
.WithModel(new WelcomeModel())//这知道它想要WelcomeModel
//否则应该抱怨编译器错误
我在这里展示的代码没有编译,因为
T
是未知的。但是这
T
无法推断:

public ITemplate GenerateTemplate(EmailType EmailType)
这给我留下了:

引擎
.GenerateTemplate(EmailType.Welcome)
.WithModel(新WelcomeModel());
这是可行的,但我觉得我在传递冗余信息——枚举和模型,而你可以从另一个中推断。我不确定我是否从C#中遗漏了什么,或者我的整个概念不好。我认为我已经走到了死胡同,因为我认为我无法从一个方法返回两个独立的强类型类


是否可以基于枚举输入返回泛型模型?

您就不能这样做吗

switch (emailType)
{
    case EmailType.Welcome:
        return engine.GenerateTemplate().WithModel(new WelcomeModel());

    case EmailType.Reminder:
        return engine.GenerateTemplate().WithModel(new ReminderModel());
}

public ITemplate<T> GenerateTemplate<T>()
{
    return new EmailTemplate<T>();

    // ...
}

public interface ITemplate<T>
{
    void WithModel(T model);
}

public class EmailTemplate<T> : ITemplate<T>
{
    void WithModel(T model)
    {
        // ...
    }
}
开关(emailType)
{
案例电子邮件类型。欢迎:
返回引擎.GenerateTemplate().WithModel(新的WelcomeModel());
案例电子邮件类型。提醒:
返回引擎.GenerateTemplate().WithModel(新的提醒模型());
}
公共ITemplate GenerateTemplate()
{
返回新的EmailTemplate();
// ...
}
公共接口项目板
{
空隙模型(T模型);
}
公共类EmailTemplate:ITemplate
{
带模型的void(T模型)
{
// ...
}
}
是否可以基于枚举输入返回泛型类

不,不会对打电话的人有用

您的方法返回
ITemplate
。但是
T
必须在编译时定义。您不能将定义推迟到运行时,除非使用后期绑定(即
dynamic
)或非类型安全机制(这否定了使用泛型的全部意义)

如果您可以重新构造您的问题并解释为什么您认为在调用站点不了解类型参数
T
的情况下调用返回开放泛型类型
ITemplate
的方法是合理的,那么可能会找到一个有用的解决方案

但正如你在问题中所说的,到目前为止,唯一真正的答案是,不,这是行不通的,如果可以的话,也没有任何意义。

不,因为C#不支持真正的泛型多态性和菱形运算符,还不允许写入:

public Template<> GenerateTemplate(EmailType emailType)
{
  switch (emailType)
  {
    case EmailType.Welcome:
        return new EmailTemplate<WelcomeModel>();
    case EmailType.Reminder:
        return new EmailTemplate<ReminderModel>();
  }
}
但在您的情况下,如果您喜欢使用真正的泛型,则需要创建几个方法:

EmailTemplate<WelcomeModel> GenerateWelcomeTemplate()
  => new EmailTemplate<WelcomeModel>();

EmailTemplate<ReminderModel> GenerateReminderTemplate
  => new EmailTemplate<ReminderModel>();
这里的代码更干净


但是我不明白为什么在创建
EmailTemplate
之后,您提供了
WithModel(new WelcomeModel())
…这是多余的,不是吗?

WithModel是否也是通用的?试着将其设置为
WithModel(t model)
我可以用model使
通用,但这样它可以接受任何模型,而不是我想基于枚举强制执行的模型?我认为,如果不创建一些奇怪的反射,你不可能做到这一点,甚至可能没有。也许你可以使用分析器强制开发人员。但是,你需要一种方法将枚举值映射到一个模型。我认为将引擎设置为可注入的,以便其他服务可以使用它编写消息
engine.Generate(Enum.First).With(ModelData);
,而不存在此开关逻辑
public ITemplate GenerateTemplate(EmailType emailType)
{
  switch (emailType)
  {
    case EmailType.Welcome:
        return new EmailTemplate<WelcomeModel>();
    case EmailType.Reminder:
        return new EmailTemplate<ReminderModel>();
  }
}
EmailTemplate<WelcomeModel> GenerateWelcomeTemplate()
  => new EmailTemplate<WelcomeModel>();

EmailTemplate<ReminderModel> GenerateReminderTemplate
  => new EmailTemplate<ReminderModel>();
if ( EmailType.Welcome )
  engine.GenerateWelcomeTemplate().WithModel(new WelcomeModel());