c# - 接口(interface)或 switch 语句,找到正确的模式

标签 c# design-patterns switch-statement

这个问题之前应该有人发过,但是我找不到了。

我已经写了这么长时间的东西,我坐下来写一些新东西,然后开始输入它,就好像它是我自己的模式一样。最近出现了一个项目,我发现自己正在查看自己的代码并开始思考它看起来有多臭。

 BackgroundInfoIfYouCare

在这个特定的库中,我需要向用户发送电子邮件。到目前为止,有 13 封 jar 装电子邮件。

每封电子邮件都有自己的模板(我使用的是 Razor 解析器,因此模板是用 cshtml 编写的)。 每个电子邮件模板都有一个字符串名称键。 每封电子邮件都有自己的 EF4 查询,以返回基于“成员资格”实体和所有相关数据的模型。

我有一个接受字符串的类,该字符串是电子邮件模板名称键。

该方法将运行适当的查询并返回一个列表,获取电子邮件模板。

列表和模板被传递给解析器以将每个成员合并到模板并返回一个列表电子邮件。

 EndOfBackgroundInfoIfYouCare

那么真正的问题是……最好的方法是什么?

一种方法是只使用开关

public List<Membership> Execute(string TemplateKey) {
switch (TemplateKey) 
        {
            case "SomethingExpired":
                QueryResult = new SomethingExpiredEmailQuery().ExecuteQuery();
                break;
            case "SomethingExpireIn30":
                QueryResult = new SomethingExpireIn30EmailQuery().ExecuteQuery();
                break;
            case "FirstTimeLoginThanks":
                QueryResult = new FirstTimeLoginThanksEmailQuery().ExecuteQuery();
                break;
            case "SecurityTraining":
                QueryResult = new SecurityTrainingEmailQuery().ExecuteQuery();
                break;
            case ETC ETC ETC...

另一种方法是使用接口(interface)

IEmailQuery
void ExecuteQuery()

但是如果我使用接口(interface),我仍然需要实例化 Query 类。它不节省任何代码,也不会使代码更易于维护。

通过反射(reflection),我可以做一些事情,比如用一种模式命名所有电子邮件查询: SecurityTraining 的电子邮件模板 key 具有 SecurityTrainingEmailQuery 的查询名称,我可以使用反射来实例化和调用 ExecuteQuery 方法。

在不使用反射的情况下,有没有更简洁的连接方式?

最佳答案

一个选择是拥有一个 Dictionary<string, Func<IEmailQuery>> map 。你可以这样构建它:

private static readonly Dictionary<string, Func<IEmailQuery>> MailQueryMap = 
    new Dictionary<string, Func<IEmailQuery>> {
    { "SomethingExpired", () => new SomethingExpiredMailQuery() },
    { "SomethingExpireIn30", () => new SomethingExpireIn30EmailQuery() },
    // etc
};

然后:

public List<Membership> Execute(string templateKey) {
    IEmailQuery query = MailQueryMap[templateKey].Invoke();
    var queryResult = query.ExecuteQuery();
    // ...
}

如果你能保证你只需要无参数的构造函数,你总是可以存储一个Dictionary<string, Type>并通过反射实例化它——但会有一些丑陋的转换等。

编辑:当然,如果模板的名称总是类型的名称,您可以使用

Type queryType = Type.GetType(namespacePrefix + "." + templateKey);
IEmailQuery query = (IEmailQuery) Activator.CreateInstance(queryType);
var queryResult = query.ExecuteQuery();

您可能还想考虑使用枚举而不是神奇的字符串常量。

关于c# - 接口(interface)或 switch 语句,找到正确的模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8590849/

相关文章:

c# - 无法从 C# 应用程序调用 Clojure clr 静态方法

c# - WinRT XAML - 如何设置 ListView 中所选项目的样式?

c# - CreatedAtRoute路由到不同的 Controller

c# - 设计模式以适应处理 Winform 功能的两种不同方式

java - 内部开关无法接受用户输入

c# - 隐藏 C# 窗体中的调整大小箭头

c# - 报告代码执行和设计模式?

wpf - 在Model View ViewModel中调出新窗口的最佳位置

java - 无法在 switch 语句中接收用户输入

java - 返回类型为 void 的 switch 表达式