我有一个类ClassA
,它使用我编写的客户端发送短信TextClient
,通过调用静态方法发送一些短信
TextClient.Send(string text, string destination)
// where destination is a phone number
但是,我还有一个邮件客户端类MailClient
,它发送具有相同签名的电子邮件:
MailClient.Send(string text, string destination)
// where destination is an email address
我想“注入”应该使用哪些客户端 - 这可能吗?
(注意:我知道当destination
可以容纳哪些值并且被认为有效时,可能会出现的问题可能会出现问题,但这些值是从其他地方获取的,所以这个上课并不需要打扰。这就是为什么我想首先把它抽象出去。)
答案 0 :(得分:7)
基本上,摆脱静态方法。创建一个接口(IMessageClient
),然后使用实现该接口的实例方法实现两个实现(TextClient
和MailClient
)。然后,您可以轻松地将适当的IMessageClient
注入应用程序的其余部分。
你肯定可以使用委托来避免在这里创建接口 - 但我肯定会改为使用接口:
答案 1 :(得分:4)
当然,让您的客户端实现一些发送界面。
public interface IMessageClient
{
public void Send(string text, string destination);
}
public class TextClient : IMessageClient
{
public void Send(string text, string destination)
{
// send text message
}
}
public class MailClient : IMessageClient
{
public void Send(string text, string destination)
{
// send email
}
}
public class ClassA
{
private IMessageClient client;
public ClassA(IMessageClient client)
{
this.client = client;
}
}
与Jon Skeet的答案相同,但他没有输入代码就打败了我。
答案 2 :(得分:2)
在设计此类服务时,通常最好避免使用静态类,因为它使得与其他代码分离更具挑战性。
如果您可以控制TextClient
和MailClient
类的设计和实现,我建议考虑将它们设为singleton实例类而不是静态类。然后,您可以在两者中实现公共接口IMessageSender
(见下文),并将其作为实例传递给需要进行调用的对象。
public interface IMessageSender
{
void Send( string message, string destination );
}
public class TextClient : IMessageSender { ... }
public class MailClient : IMessageSender { ... }
如果您无法控制这些类的实现(或者此时无法更改它们),您可以将委托传递给需要进行调用的对象:
class SomeConsumer
{
private Action<string,string> m_SendDelegate;
public SomeConsumer( Action<string,string> sendDelegate )
{
m_SendDelegate = sendDelegate;
}
public DoSomething()
{
// uses the supplied delegate to send the message
m_SendDelegate( "Text to be sent", "destination" );
}
}
var consumerA = new SomeConsumer( TextClient.Send ); // sends text messages
var consumerB = new SomeConsumer( MailClient.Send ); // will send emails
答案 3 :(得分:1)
不要将方法设为静态,使用Send()
方法创建接口,并在TextClient
和MailClient
上实现此接口。现在您可以使用界面注入实例。
如果无法使方法成为非静态方法,则可以在静态方法调用周围写入瘦包装器,同时实现所述接口。
答案 4 :(得分:0)
我会这么认为的。如果您有这样的界面
public interface ISender
{
void Send(string text, string destination);
}
然后使用依赖注入来获取要使用的发件人。