If you only need to instantiate those types in that method, you're right in that they shouldn't be injected into the class.
Instead, the typical solution is to inject a factory that will allow your method to resolve an interface.
Here's the usual approach:
interface IMessageFactory
{
IMessage CreateMessage(string text);
}
class ConcreteMessageFactory : IMessageFactory
{
IMessage CreateMessage(string text) { return new Message(text); }
}
class MockMessageFactory : IMessageFactory
{
public IMessage CreateMessage(string text) { return new MockMessage(text); }
}
class MyClient
{
private readonly IMessageFactory _msgFactory;
public MyClient(IMessageFactory msgFactory)
{
_msgFactory = msgFactory;
}
public void SendMessage(string text)
{
IMessage msg = _msgFactory.CreateMessage(text);
msg.Send();
}
}
//Usage:
new MyClient(new ConcreteMessageFactory());
//Mocking
new MyClient(new MockMessageFactory());
Depending on which DI framework you're using, the framework can make this way easier for you. Castle Windsor, for example, lets you inject a delegate-based factory, as opposed to the interface-based factory above:
class MyClient
{
private readonly Func<string, IMessage> _msgFactory;
public MyClient(Func<string, IMessage> msgFactory)
{
_msgFactory = msgFactory;
}
public void SendMessage(string text)
{
IMessage msg = _msgFactory(text);
msg.Send();
}
}
//Usage:
new MyClient(() => new Message());
//Mocking
new MyClient(() => new MockMessage());