C# 接口和重载

C# 接口和重载,c#,C#,我有一个关于最佳实践的问题 我有一个用于发送消息的接口。首先,我只设置为短信文本,现在我决定也实现电子邮件,但我仍然需要使用只有一个接口。现在,我的界面包含两种方法,我将其作为参数消息,这对于sms来说很好,但是对于电子邮件来说并不好,因为我的电子邮件需要具有不同的属性,例如主题 你能告诉我如何只使用一个界面,或者我应该改变什么吗 public interface IMessageSender { Task<MessageResult> SendAsync(Message m

我有一个关于最佳实践的问题

我有一个用于发送消息的接口。首先,我只设置为短信文本,现在我决定也实现电子邮件,但我仍然需要使用只有一个接口。现在,我的界面包含两种方法,我将其作为参数消息,这对于sms来说很好,但是对于电子邮件来说并不好,因为我的电子邮件需要具有不同的属性,例如主题

你能告诉我如何只使用一个界面,或者我应该改变什么吗

public interface IMessageSender
{
    Task<MessageResult> SendAsync(Message message);

    MessageResult Send(Message message);
}

public class Message
{
    public string Sender { get; set; }

    public string Reciever { get; set; }

    public string Body { get; set; }
}

public class EmailMessage : Message
{
    public string Subject { get; set; }
}
公共接口IMessageSender
{
任务发送异步(消息);
消息结果发送(消息消息);
}
公共类消息
{
公共字符串发送方{get;set;}
公共字符串接收器{get;set;}
公共字符串体{get;set;}
}
公共类EmailMessage:Message
{
公共字符串主题{get;set;}
}

传统上,基本
消息
类型包括一个名为
Send()
的虚拟方法。然后有
SMSMessage
EMailMessage
的类型,它们覆盖了
Send()
方法,以便多态性可以决定调用哪一个

新的范例不太喜欢这个,因为单元测试可能会更难。您可以测试单个
Send()
方法,但不能测试是否会立即调用正确的方法。因此,我们有一些东西,比如控制反转、存根/模拟等,它们通常希望您编写和实现额外的接口,比如
IMessageSender
,以添加一个抽象层,您可以在其中验证这是否正确发生

这给了我们一个新问题:如何知道使用了正确的
MessageSender
?现在我们添加了另一个模式:
MessageSenderFactory()
,它接受
消息
,并返回正确发送者类型的实例

就像你在写Java一样



关键是要仔细看看你想在这个兔子洞下走多远现在,这种情况可以通过一个简单的
if()
条件来解决,条件是您要发送什么类型的消息
,但是来自不同编程规程的模式将要求您在其上添加几个层。他们没有错。附加的层和约定确实在测试、灵活性、适应性、可靠性和可识别模式方面增加了有意义的价值。很多时候,它们是我们要走的路。但它们也增加了软件的复杂性、代码和认知负荷。因此,了解这一点也很有价值。

您可以将
主题
属性添加到
消息
。这不会改变界面。然后,在SMS实现中,如果提供了
主题
值,则将其作为消息的第一行,通过回车或其他方式与
正文
隔开。因此,您希望创建一个接口来处理概念上不同的两件事情。“消息”要么有主题,要么没有主题。否则,请使用类似于
.Send()
方法的方法创建一个
IMessage
接口,该方法允许消息将自身写入输出流(或其他内容)我的发送方法是在界面中,我试图将其抽象化,但是我必须实现body,这对于sms和email的提供商来说是非常不同的,所以你认为我应该为email实现另一个界面吗?对不起,我不明白,在某些时候,你必须实现发送短信和电子邮件。这是没办法的。我是说你应该仔细看看你到底想从这个兔子洞里钻多远。现在,这种情况可以通过一个简单的
if()
条件解决。但是不同的编程规程可能会要求您在上面添加一层又一层。他们没有错。额外的层和模式确实在测试、灵活性、适应性、可靠性和可识别的模式方面增加了价值。但它们也增加了软件的复杂性、代码和认知负荷。所以对这一点的认识也是很有价值的。哦,Java。。。我的日子变得更糟了。