I know how to make pluggable things in c#. Define an Interface, Activator.CreateInstance(<class>), etc. Or I can have a code path that explicitly creates an instance of the plugged class. Many ways.
But what if the service I want to make pluggable is static (I know I could refactor so that it's not but that's not the point of the question)
Concrete example. I have a class that provides disk I/O abstraction (Read File, List Directory,....). Now I want different implementations of this abstraction that serves up files from , say, a real FS, a database.
Based on Olivier Jacot-Descombes reply, I will have a FileSystem class (that is real) like this
public static class FileSystem
{
static IFSImplemenation s_imple;
static FileSystem()
{
if(<some system setting>)
// converted to singleton instead of static
s_imple = new OldFileSystem()
else
s_imple = new DbFileSystem();
}
public static byte[] ReadFile(string path)
{
return s_imple.ReadFile(path);
}
...
}
To reiterate - I have a large body of code that I dont want to change so it was important to keep the calling signature the same - this solution achieves that
You can't, and that's a limitation of the type system in .NET and most object-oriented systems/languages.
The reason being that "pluggable things" (as you refer to them) require polymorphism in order to be effective.
You define a contract (an interface, in .NET-speak), and then you implement that contract. Your system only ever deals with the contract.
Static members are not polymorphic in .NET, so you can never get them to implement a contract.
For your example of disk I/O abstraction, you wouldn't create a static class for this, you'd create an interface, and implement the interface, passing around the interface.
Of course, the benefits of using an interface are that it's easier to test both sides of the implementation of your contract:
In the case of your disk I/O abstraction, for everything that calls your contract, you would never have to worry about actually touching the file system, you simply have to make the contract behave (through proper mock setup) as if it were touching the file system.
If you have an existing service that is exposed through static members, and you want the ability to swap that out with another implementation, then you'll have to do the following:
Use your static class as facade for non-static implementations
public static class DB
{
private static IDbInterface _implementation;
public static void SetImplementation(IDbInterface implementation)
{
_implementation = implementation;
}
public static Customer GetCustomerByID(int custId)
{
return _implementation.GetCustomerByID(custId);
}
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With