Base project dll reference not found in upper layers - c#

In my current architecture I have the following project organization...
An class library named "MyBaseProject" and different web application projects with reference to MyBaseClassLibrary.
In MyBaseProject I added a 3rd party dll (Newtonsoft.Json)
Now all web projects are throwing the exception "Could not load file or assembly Newtonsoft.Json or one of its dependencies."
I do not want to add the Newtonsoft.Json in all my web projects, what should I do?

See How the Runtime Locates Assemblies.
The most obvious behaviour here is that you have not set the output directory for your projects, and thus they're defaulting to their own, individual locations. Thus, while MyBaseProject references and copies Newtonsoft.Json, your other projects only copy over MyBaseProject. Because of this, the MyBaseProject.dll located in the folder with the other projects does not have a copy of Newtonsoft.Json, and since it's not in the GAC, the reference fails.
The easiest solution is to make all your projects output to the same directory. I'm personally fond of $(SolutionDir)\bin\$(Configuration)\$(Platform). This will ensure that when MyBaseProject.dll is built and carries along any of its requirements, your other projects will be able to get those requirements via the same folder without incident.

Related

How to deploy a dependent DLL when a client solution references my project?

I have a C# project which builds a library DLL, myLib.dll. This DLL has a dependency on a 3rd party DLL, dep.dll (which I provide but do not build).
I want others to be able to use my library by adding my project to their solutions and referencing it. Adding my project as a reference automatically copies myLib.dll to the Target directory of their app, but of course dep.dll is not copied with it.
Bear in mind that I have no control over where my project is in their code tree, and the DLL can't know where it was copied from.
The only solution I can see is to force the user to add a build event which copies dep.dll to their target directory. We can't assume users can create environment variables.
This is very undesirable for several reasons (it's not really one dependency - I simplified things, I don't want them to have to be concerned about the dependencies in my project, and it's very fragile - adding an extra dependent DLL to my project would require everyone to update their build scripts).
I can't load the dep.dll directly as I don't know where it is - my build scripts can copy it to the same target directory as myLib.dll but the actual version of myLib.dll they run will have been copied somewhere else.
I also can't make dep.dll a reference directly (probably because it's not a .NET assembly). I just get "Error loading code-completion information for dep from dep.DLL. Format of the executable (.exe) or library (.dll) is invalid".
So is there any way to have the dependent DLL just seamlessly copied with myLib.dll when a client builds their application? [I'm using Sharp Develop if it matters.]
Can you add dep.dll to your projects root folder as a file like a .cs file. Set the Build Action to None and Copy to Output Directory to Copy if newer.

Missing DLLs from a class library that uses separate DLLs

In C# .NET 4.0 I am creating a class library / DLL that I plan to reuse in many other projects. This class library will use several DLLs itself. For example, the class library I am creating may reference several DLLs like:
ServerConnectorLibrary references:
Lib1.dll
Lib2.dll
Lib3.dll
When I build this, I get ServerConnectorLibrary.dll as the output in the bin\Debug folder.
What I want now is to use this ServerConnectorLibrary.dll in other projects. However, when I add the DLL to my new projects and run I get the following error:
FileNotFoundException: Could not load file or assembly "Lib1.dll".
If I add Lib1.dll to the bin\Debug folder of my new project, the problem is not solved.
You may be able to combine all of your dependencies into a single assembly. Here is an old example on CodeProject.
http://www.codeproject.com/Articles/9364/Merging-NET-assemblies-using-ILMerge
There is also a StackOverflow thread here...
How do I merge multiple .net assemblies into a single assembly?
Otherwise, make sure the properties for each dependency is set to copy local and then include the dependencies along with your library. These are DLLs, so they are dynamically linked at run-time, unlike older C++ and C libraries that might be statically linked.

access referenced projects at runtime

I have a rather strange project where I need to check the assemblies of the projects included as references in my project to see if they contain a certain Type. As far as I can tell the only way to see which projects are in my solution is to parse the solution file - which I can't do at runtime since I don't have it.
Does anyone know a way to see, at runtime, which assemblies are in the project file?
To check the referenced assemblies in your project assembly at runtime, you need to use Reflection.this.GetType().Assembly.GetReferencedAssemblies()

Class Library - References - Reusability with Copy Local?

I have a class library project, lets call it CoreLib.
CoreLib has two references to 3rd party DLL files 1.dll and 2.dll
Because I love reusability so much, I want to be able to use CoreLib in as many places as possible/needed.
So if I had a project called BigProjectA and another project called BigProjectB and they needed to leverage the functionality provided by CoreLib, all I would have to do is add a reference to CoreLib in those projects (BigProjectA and BigProjectB).
That is fine, except when I go to copy over my output folder (bin directory) to another person's computer, I can't guarantee that they have 1.dll and 2.dll on their machines.
For that, I just set Copy Local to True for 1.dll and 2.dll references in the CoreLib project.
When building the CoreLib project I can see 1.dll, 2.dll, and CoreLib.dll files. That is PERFECT!
But in the projects referencing CoreLib, only CoreLib.dll is copied over, not 1.dll and 2.dll.
Am I missing something? Copy Local set to True, but only copies for the CoreLib project. So even though they are in the same solution, and I'm adding CoreLib as a project reference to the other projects, I still dont see 1.dll and 2.dll copying out to the other bin/Debug, bin/Release folders of the other projects (BigProjectA and BigProjectB).
Is there an easy solution?
The easy solution is to either:
reference 1.DLL and 2.DLL in projects which have a binary reference to CoreData.DLL
Add CoreData as a project reference to BigProjectA and BigProjectB instead of as a binary reference
In the first scenario, CoreData's dependencies are not automatically output by the compiler. If the CoreData project is added to the solution, its dependencies will be output. Hence, to use CoreData as a binary reference, you must also reference its dependencies.
There is nothing wrong. In projects BigProjectA and BigProjectB you have a references to only CoreLib, so they "care" about coping only it, cause they have no any clue about it's dependencies. What you can do to resolve these kind of issue, is to add for example PostBuildVEent in your BigProject.. to copy also CoreLib dependencies.
Or add reference to CoreLib project, if you can.
Another solution, is to consider DI like a technique to avoid strong coupling of references. So, if in BigProjectA or B you don't care about functionality provided by 3rd party libraries in CoreLib, for you should be enough to just copy CoreLib.
Good answers guys....but I actually just ended up using ILMerge. Seemed safer/less annoying.
Thank you though

Where should you store 3rd party assemblies?

Okay, so we have a rather large solution with about 8 different projects inside it. Each of these projects depend on various different 3rd party assemblies. This solution is in the trunk branch of source control. We also have about 5 different branches off of trunk.
What is the best way to manage these 3rd party assemblies? When you add a reference to an assembly and then click it and view the properties window I notice that it has a hard coded path to the assembly.
For example: All our branches are mapped to "C:\Code\". So trunk would be "C:\Code\Trunk" and a branch would be "C:\Code\somebranch".
If I create a folder in "C:\Code\Trunk" called "Assemblies" and then drop all our 3rd party assemblies in that folder, and then I add a reference to an assembly in there is that assembly reference relative? If I click the added assembly I see the grayed out path property says "C:\Code\Trunk\Assemblies\someassembly.dll".
What happens if I then branch off of trunk? Would "somebranch" still have a reference to "C:\Code\Trunk\Assemblies\someassembly.dll" or would it then reference "C:\Code\somebranch\Assemblies\someassembly.dll"?
Currently we actually have a branch in source control called "Assemblies" which is mapped, just like any other branch, to "C:\Code\". So all branches with projects referencing assemblies have references to "C:\Code\Assemblies\someassembly.dll" no matter which branch the project is in, the path would be the same.
Unfortunately this means that you have to get the latest version of the branch you are working in AND the assemblies branch in order to get the solution to build successfully.
To sum it all up:
How do you add a reference that is relative to the solution? (i.e. Add a reference to C:\Code\Trunk\Assemblies\someassembly.dll and have that path be relative to the project that added it, so that when creating a branch it references the branched assemblies folder and not trunk's assemblies folder. Or is this reference already relative?
What are other recommended strategies for managing 3rd party assemblies?
Now we have nuget you can use it for all supported oss packages and even create your own nuget packages for other 3rd party assemblies. It is worth mentioning openwrap as an alternative to nuget.
nuget stores packages at solution level
so each branch (and trunk) would keep a version of these.
I'd suggest this is preferable behaviour. You would want to keep your assemblies version separate if upgrading a 3rd party for example.
In the past I've used svn's externals command to build the specific version from the internally developed dependencies. There's no reason you couldn't stick those in a repository and use externals (or you scm's equivalent) to get the right version.
I've used build events to get the dlls into the right place too.
Yes use an assemblies folder off of the trunk. I like the name lib better then assemblies.
Yes the path is already relative. When you branch your projects will get the correct assemblies folder.
Depending on how many third party assemblies you are using you make also want to organize your assemblies folder so it is not one big mess of dlls.
We have a SolutionItems folder in our solution for the 3rd party references.
Every branch of the solution has it's own copy.
When we add a reference we use the 'Browse' tab in the add reference dialog and select the assembly relative to our current project.
The Project file contains this:
<Reference Include="SomeAssembly, Version=0.1.0.0, Culture=neutral, PublicKeyToken=8xxxxxxxxxxx, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\Solution Items\SomeAssembly.dll</HintPath>
</Reference>
I usually create a common project that all the others reference. Inside that common project, I create a folder called deps (for dependencies). Each of the other projects then references the copy of the DLL in the common project's deps folder.

Categories

Resources