0

I want to be able to write a function which uses code from a library (lets call it libx) without having to change the code around depending on which version of libx I am using.

For example

public string ReturnFormattedString(string input) {
    //If using version 1 of library
    return libx.SomeClass.FormatString(input);
    //If using version 1 of library

    //If using version 2 of library
    return libx.SomeNewClass.FormatString(intput); 
    //Note: libx.SomeNewClass is not available in version 1
    //If using version 2 of library
}

I am not even sure if this is possible, but I would like to know how such a thing could be achieved, so that I could be able to compile my code without having to do any changes depending on which version of libx is in use.

Edit:

Just to clear some things up. I do not have access to the code of libx. My application is a plugin that works on top of another program which uses libx. So the version of libx depends on the version of the program I am plugging into.

I'm starting to think this might not be possible without having two different assemblies each with a different implementation of ReturnFormattedString according to which version of libx I am targeting (which is what I wanted to avoid in the first place).

omarello
  • 2,683
  • 1
  • 23
  • 23
  • Reflection would really be the only way to "sort-of" achieve this... though even then I don't think you would be able to ensure that it would *never* break. If you had access to the code in the library, there may be some other ways to get what you want, but either way you will have to change code at some point. Typically the writer's of libraries do not change class names though for this very reason. – Evan L Jun 24 '14 at 15:34
  • One would expect the library to be backwards compatible, so if you're going to write everything in the older version's methods, why not just use all of that code if they have a newer version? – Servy Jun 24 '14 at 15:34
  • Why you didn't pack the `SomeNewClass` in the new assembly? – Hamlet Hakobyan Jun 24 '14 at 15:36
  • Seems you're looking for MEF? – Federico Berasategui Jun 24 '14 at 15:38
  • Are you trying to use the `alias` keyword? http://stackoverflow.com/questions/14708633/using-two-different-versions-of-the-same-dll-in-an-asp-site-using-two-sdks – Aron Jun 24 '14 at 15:41

2 Answers2

0

In this case you are returning a string, so the implementation change is not visible to the caller even if the code does change. However, generally you can use interface based programming:

public string ReturnFormattedString(string input, iSomeClass myInjectedClass) {
    //If using version 1 of library
    return libx.myInjectedClass.FormatString(input);
    //If using version 1 of library

    //If using version 2 of library
    return libx.myInjectedClass.FormatString(intput); 
    //Note: libx.SomeNewClass is not available in version 1
    //If using version 2 of library
}

Now the caller defines the implementation via Dependency Injection.

Combined with good OO design you have the best possibility of having maintainable code that achieves the open-closed principle.

Of course, realistically scope creep and/or changing requirements could eventually result in a breaking contract change. That's just life.

P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348
  • But that's *not* an option. As it is, this library will need to be compiled with both libraries as dependencies, so when someone using the library goes to use it they'll get errors if they don't have *both* libraries. There's no real effective way to tell the C# compiler, "I need just one of these two libraries." You can dynamically load the assemblies, but then you need to do the entirety of your coding in reflection, not compiled code. – Servy Jun 24 '14 at 15:42
  • Just add dependency injection. Add a parameter to the function so the caller passes in the interface. – P.Brian.Mackey Jun 24 '14 at 15:51
  • That doesn't work when you're deciding whether or not to use a dependency *at runtime*. It's only an option when deciding what dependency to use *at compile time*. Also remember that the caller of this method is designed to be unaware of this behavior, not adjusting how it calls the method. If that were an option, you'd just create two different assemblies, one targeted to each version of the dependency. – Servy Jun 24 '14 at 15:52
  • 1
    Could be wrong... I don't believe the OP is referring to varying support dynamically at runtime; I think it's a convenience feature. Dependency Injection would be a good option most likely. – Brian Mains Jun 24 '14 at 15:57
0

As a project needs a hard-dependency somewhere, one project support I wouldn't recommend unless you add every DLL as a reference.

You can certainly offset cost and complexity with advanced design patterns as @P.Brian.Mackey mentioned, such as dependency injection. I am a supporter of using design patterns to solve complexity in code. However, that can be cumbersome if you are talking about handling a couple of classes, so scope is important here. Or most of your code can be a central library (which may or may not be a PCL), and only the variances are in a subproject, one for each version you need.

It's also possible to do what you are asking, with a separate project per version, with the use of custom conditional symbols. In VS Project settings > Build tab, there is a Conditional compilation symbol textbox, which whatever you put there you can do:

#if VERSION1
#else
#endif

And use that to vary logic by target framework (see for more info). All you have to do then is change the symbol, or put the code in a folder, and have multiple project files there pointing to the same code, each with it's own compilation symbol. That can be tedious because you have to constantly map files, but you could use a tool like Project Linker to manage that.

Brian Mains
  • 50,520
  • 35
  • 148
  • 257
  • That results in the ability to create two versions of his library, one targeted to each framework, which is very different from a *single* library that uses whichever of the two external libraries is available. – Servy Jun 24 '14 at 15:43
  • Again, it's still not what the OP is asking for, which is a single assembly that uses the appropriate dependency. Creating two different assemblies, one for each dependency, is what he explicitly said he didn't want to do. – Servy Jun 24 '14 at 15:57
  • Exactly. I need to create one assembly that uses the appropriate dependency – omarello Jun 24 '14 at 17:18
  • If you want type specificity but not add every DLL as a hard reference, you can't do what you want to do. Otherwise, you are going to need to use reflection to load the assembly based upon the version of libx in the assembly list, and use reflection to call the methods on the API, which loses type specificity. – Brian Mains Jun 24 '14 at 17:41