views:

45

answers:

2

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?

+2  A: 

Hide 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.

Mark Seemann
My current approach is similar to the one you described, the boolean that the function returns is used to decide whether some actions should take place or not (So I'm returning true whenever FSRM is not present). As for using config files, I was hoping to somehow detect the presence of the library dynamically.
apoorv020
+3  A: 

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.

Craig Trader
If I am dynamically loading a reference, then how will code using the reference compile? The compiler should know about the existence of classes in the reference.
apoorv020
@apoorv020, Updated my answer to point to example code.
Craig Trader