2

I created a C# application (MyAppV1) that requires a third party API. My application needs to work with multiple versions of this API, but only a single version at one time. I have setup my solution to change the reference and using statement for different build configurations and I create multiple executable files that each target a different API version.

Presently I have this situation:

  • MyAppV1_ThirdPartyV1.exe uses ThirdPartyV1.dll
  • MyAppV1_ThirdPartyV2.exe uses ThirdPartyV2.dll
  • MyAppV1_ThirdPartyV2_5.exe uses ThirdPartyV2.dll (they didn't change the library name for the minor version of their software)
  • MyAppV1_ThirdPartyV3.exe uses ThirdPartyV3.dll

I would like to be able to maintain a list of the versions, perhaps in an App.config and load the appropriate dll library at runtime. I'm having trouble knowing where to begin with this. Is this an appropriate strategy? I'm not sure how best to handle this situation. Multiple versions of my application the only differ with the referenced library seems very clunky to me.

Much of the information I find is related to supporting multiple frameworks, handling the requirement of two versions of the same library downstream at the same time, or needing to load both at the same time. I can't find information on how to handle my particular situation.

  • can't you host a single solution with 3 different projects ? seems to me you are more than doubling your efforts – MethodMan Dec 18 '18 at 20:08
  • This thread should help https://stackoverflow.com/questions/18362368/loading-dlls-at-runtime-in-c-sharp – YouneS Dec 18 '18 at 20:12
  • Are the versions of the third-party library _backwards compatible_ (i.e., can you use a newer version as a drop in replacement for an older version). If so, look at configuration/runtime/assemblyBinding/dependantAssembly/bindingRedirect in config files. If not, I'm very glad I'm not in your shoes – Flydog57 Dec 18 '18 at 20:13
  • 1
    if you want to ship one single exe and user can swap out the dll as they need then you need to use reflection dynamic dll loading. If not then just build 3 versions. Dynamic dll loading is not type safe and gets ugly real quick – Steve Dec 18 '18 at 20:14
  • Possible duplicate of [Using multiple versions of the same DLL](https://stackoverflow.com/questions/5916855/using-multiple-versions-of-the-same-dll) – paulsm4 Dec 18 '18 at 20:16
  • @paulsm4 - it is not a duplicate, that question deals with loading multiple version at the same time. I stated I would like to use "only a single version at one time", thank you for your response. – user3493725 Dec 20 '18 at 03:12
  • @MethodMan - I have my solution setup with different configurations as T.S. mentions below. I think multiple projects would be more work to maintain and doesn't allow me to produce one executable that could use multiple libraries depending on the users choice. Thank you for your comment. – user3493725 Dec 20 '18 at 03:15
  • @YouneS I will take a look, thank you for the suggestion. – user3493725 Dec 20 '18 at 03:21
  • @Steve At the moment I'm struggling with my users running the wrong version and complaining my application doesn't work. They sit around and wait for my response rather than use their heads, I'd rather do the work but I take your point that it won't be easy. Thanks for the suggestion. – user3493725 Dec 20 '18 at 03:24
  • @Flydog57 I simply update my configuration to point to the new library and recompile. Fortunately the area of the API I require has been fairly stable for the last 4-5 years. I'll look into your suggestion, thank you. – user3493725 Dec 20 '18 at 03:26
  • @Flydog57 https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/bindingredirect-element This appears to be a way so the application may choose the latest library automatically based on what is available. My users often use different versions based on the job they're working on, they can't always update their analysis models to the latest version of the software. I can't assume they always want the latest. I don't think this will work. Thanks for your suggestion. – user3493725 Dec 20 '18 at 03:48
  • @user3493725 or you could just check the version in code and throw exception if the version doesnt match – Steve Dec 20 '18 at 15:29

1 Answers1

0

This is possible on project level. You can build different configurations in solution and when you add references as below, it will take the desired DLLs

<Choose>  
  <When Condition="'$(Configuration)|$(Platform)'=='YourSpecialConfiguration1|x64'"><!-- attention here -->
    <ItemGroup>
      <Reference Include="your.dllv1.name">
        <HintPath>yourDllPath_v1\your.dllv1.dll</HintPath><!-- attention here -->
        <Private>true</Private>
      </Reference>
      <!-- more references here -->
    </ItemGroup>
  </When>
  <When Condition="'$(Configuration)|$(Platform)'=='YourSpecialConfiguration2|x64'"><!-- attention here -->
    <ItemGroup>
      <Reference Include="your.dllv2.name">
        <HintPath>yourDllPath_v2\your.dllv2.dll</HintPath><!-- attention here -->
        <Private>true</Private>
      </Reference>
      <!-- more references here -->
    </ItemGroup>
  </When>
  <Otherwise>
    <ItemGroup>
      <Reference Include="your.dllname">
        <HintPath>yourRegularPath\your.dllname.dll</HintPath><!-- attention here -->
        <Private>true</Private>
      </Reference>
      <!-- AND more references here -->
    </ItemGroup>
  </Otherwise>
</Choose> 

What you see above - option 1.

Option 2 - Different projects for each version. Downside - if you add a file or reference , you need to add to each project

Option 3 - Add all references but declare different namespace aliases (in reference property window) for each. Then in code do conditional compilation like

ISomething myVar;

#if V1
    myVar = new namespace1.ClassX();
#elif V2
    myVar = new namespace2.ClassX();
#else
    . . . .
#endif

And lastly:

"I would like to be able to maintain a list of the versions, perhaps in an App.config and load the appropriate dll library at runtime."

- you probably don't need non of these. You just need to produce your packages with different versions. Loading at runtime will require more coding work while still supplying all DLLs because you don't know what you going to load next time.

T.S.
  • 18,195
  • 11
  • 58
  • 78
  • Hi @T.S. I'm already doing as you suggest in Option 1. Option 2 sounds like more work to maintain than the present situation but doesn't address my desire for a single executable that could load the appropriate dll on request. I'm not sure I follow what you suggest for Option 3 "You just need to produce your packages with different versions.", this is precisely what I'm currently doing. Thank you though, I appreciate your detailed response. – user3493725 Dec 20 '18 at 03:19
  • @user3493725 Do you know what is binding redirect is? There we go - you can compile your code against one version of dll, but run against different version of same dll. Simply supply the DLL and entry in config file. By modifying this entry and changing the dll, you can work against any dll version you want. That is if signature is same. – T.S. Dec 20 '18 at 03:45
  • I don't believe that will work. I need the user to specify (or my app can choose from a list). It is not always the case that the latest version is the required version. My application requires a running instance of an engineering analysis software, they typically maintain a few versions at a time to support old projects. They rarely upgrade their models but they do use the latest software when beginning new projects. – user3493725 Dec 20 '18 at 04:06
  • @user3493725 Besides techniques above, you also have ability to load any assembly using reflection and call methods there. You can load assembly into domain and if it can't be loaded into same domain, you can load it into different domain. Right now, I starting to feel that you have not clearly defined you "path to success". Often OPs ask for something without even knowing about better ways (read - designs). When you say *"I need the user to specify..."* - specify version of referenced dll? if you in runtime already - only reflection. If prior to runtime - you can make "startup app" where.... – T.S. Dec 20 '18 at 15:07
  • ... they pick the version, your startup app modifies binding redirect and starts actual app binding it to needed version of DLL. – T.S. Dec 20 '18 at 15:08
  • You're right, I'm uncertain about better ways hence why I asked if what I wanted was an appropriate strategy. Thank you though, I certainly have found myself in an area where I'm lacking knowledge. There doesn't appear to be an easy or well defined solution I can examine. – user3493725 Dec 20 '18 at 20:24