Reputation: 143
I have a IConsole
interface, describing how to write stuff to the console, and one implementation, upperCaseConsole
.
IConsole is injected in the Foo
class using Unity.
public interface IConsole {
void WriteLine(string text);
}
public class upperCaseConsole: IConsole {
public void WriteLine(string text){
Console.WriteLine(text.ToUpper());
}
}
public class Foo{
private readonly IConsole console;
public Foo(IConsole console){
this.console = console;
}
public void WriteStuff(string stuff){
console.WriteLine(stuff);
}
}
I would now like to change how the text is written to the console. I have done a good job decoupling the implementation from foo, and I can just inject a new implementation, say lowerCaseConsole
instead.
public class lowerCaseConsole: IConsole {
public void WriteLine(string text){
Console.WriteLine(text.ToLower());
}
}
My problem is, despite my best tests, I am not really sure that lowerCaseConsole
will do the job, and I would like to run both implementations simultaneously for a while.
How can I do it without duplicating all the code in Foo
?
I would like to avoid something like:
public class Foo{
private readonly IConsole lowerConsole;
private readonly IConsole upperConsole;
public Foo([Dependency("lower")] IConsole lowerConsole,
[Dependency("upper")] IConsole upperConsole){
this.lowerConsole = lowerConsole;
this.upperConsole = upperConsole;
}
public void WriteStuff(string stuff){
lowerConsole.WriteLine(stuff);
upperConsole.WriteLine(stuff);
}
}
Note: The real-life case is that I am about to move forward on a DB change. I would like to transparently start writing to the new DB, and see how things go, but keep writing to the current DB, just in case.
Upvotes: 2
Views: 55
Reputation: 9529
You could use named registration to inject IEnumerable<IConsole>
. This approach is easily extendable with more implementations...or you could easily remove one of them...
container.RegisterType<IConsole, LowerConsole>("LowerConsole");
container.RegisterType<IConsole, UpperConsole>("UpperConsole");
container.RegisterType<IEnumerable<IConsole>, IConsole[]>();
then the ctor of the Foo
becomes a bit different and also the WriteStuff
method...
public Foo(IEnumerable<IConsole> consoles)
{
this.consoles = consoles;
}
public void WriteStuff(string stuff)
{
foreach(var console in consoles)
{
console.WriteLine(stuff);
}
}
Upvotes: 1
Reputation: 37070
One option would be to create a third implementation that contains private members of the other two, and calls to it's WriteLine
method would just be forwarded to both the other types.
public class BothCaseConsole : IConsole
{
private readonly LowerCaseConsole lcc = new LowerCaseConsole();
private readonly UpperCaseConsole ucc = new UpperCaseConsole();
public void WriteLine(string text)
{
lcc.WriteLine(text);
ucc.WriteLine(text);
}
}
Then just inject this type into Foo
:
new Foo(new BothCaseConsole()).WriteStuff("Stuff to write");
Upvotes: 4