I am working on a project and want to optionally use an assembly if available. This assembly is only available on WS 2008 R2, and my ideal product whould be a common binary for both computers with and without the assembly. However, I'm primarily developing on a Windows 7 machine, where I cannot install the assembly.
How can I organize my code so that I can (with minimum changes) build my code on a machine without the assembly and secondly, how do I ensure that I call the assembly functions only when it is present.
(NOTE : The only use of the optional assembly is to instantiate a class in the library and repeatedly call a (single) function of the class, which returns a boolean. The assembly is fsrmlib, which exposes advanced file system management operations on WS08R2.)
I'm currently thinking of writing a wrapper class, which will always return true if the assembly is not present. Is this the right way to go about doing this?
views:
45answers:
2Hide the functionality behind an interface, say:
public interface IFileSystemManager
{
void Manage(IFoo foo);
}
Create two implementations:
- An implementation that wraps the desired functionality from fsrmlib
- A Null Object implementation that does nothing
Inject the IFileSystemManager into your consumers using Constructor Injection:
public class Consumer
{
private readonly IFileSystemManager fileSystemManager;
public Consumer(IFileSystemManager fileSystemManager)
{
if (fileSystemManager == null)
{
throw new ArgumentNullException("fileSystemManager");
}
this.fileSystemManager = fileSystemManager;
}
// Use the file system manager...
public void Bar()
{
this.fileSystemManager.Manage(someFoo);
}
}
Make the selection of IFileSystemManager a configuration option by delegating the mapping from IFileSystemManager to concrete class to the config file so that you can change the implementation without recompiling the application.
Configure applications running on WS 2008 R2 to use the implementation that wraps fsrmlib, and configure all other applications to use the Null Object implementation.
I would recommend that you use a DI Container for the configuration part instead of rolling this functionality yourself.
Alternatively you could also consider treating the IFileSystemManager as an add-in and use MEF to wire it up for you.
My approach would be to dynamically load the assembly, instead of hard-coding a reference. Your code could then decide whether to use the assembly (if it loaded) or return some other value. If you use the assembly, you'll need to use reflection to instantiate the class and use the method. That way your code will build and run on any platform, but it's behavior will change if it detects the presence of fsrmlib
.
The System.Reflection.Assembly documentation has example code for doing this.