Missing DLL's own dependencies in consuming projects - c#

I created a class library project using C# and .Net.
In this project I used two external dependencies(to be more specific: Microsoft.Win32.Registry(4.6.0) and System.Data.SqlClient(4.7.0) Nuget packages).
After I build this project, I can see the generated DLL file under /bin/debug folder.
Now I want to import this generated DLL in another project and consume its methods. Once imported and I run this project, it complains about not being able to find those two external dependencies I had in class library project.
As a temporary fix, I can import these two missing references in this project and it will work fine and as expected. But this is not what I want(and I guess is not a clean solution as well).
I want to know why the dependencies of class library project is not reflected in generated dll file? And is there any way to fix this?
Many thanks for your help.

If your class library is in the same solution or source control repository as the app that's using it, you should use a project-to-project reference, rather than referencing the assembly directly. As the docs say, this way it automatically detects changes to the class library when you compile the app, but what the docs didn't say is that dependencies flow though as well.
Otherwise, as Lance Li wrote, you should create a NuGet package from your class library. Unfortunately there's a bit of a barrier to get started. Creating the package is easy, but then you need to publish the nupkg file somewhere. For early development (before the package is ready to be shared), the easiest option is to use a local file feed. You'll then need a nuget.config in the app that will use the package to add that local feed as a source, then you can install the package in your consuming project, which will bring dependencies.
As you can see, for development, this is slow and difficult because if your consuming app finds a bug in your package, or if you're trying to develop a new feature in both the consuming app and class library at the same time, it means every time you make code changes to class library, you need to increment the version number, pack a package, publish the package, then update the package version in the consuming project. It's far, far easier to use a ProjectReference which lets you simply edit code, compile, run. Nothing else to think about.

See this, the way you reference that assembly is not a recommended way when both the projects are in same machine.
You're using the file reference(Add reference => browse...). And that's why you have to import these two missing references in this project manually.
So I suggest you add the project reference, if both the two projects are in same solution, you can right-click current project=>add reference=>project tab find that assembly you need.(instead of browsing...)
If the referenced project is not in same solution. Right-click solution in solution explorer=>add existing project to import it. Then add project reference.

Related

Converting a C# class I created inside a project to a separate reusable class

I'm not new to C# programming, but I suppose I'm new to programing "the right way" in C#. I've worked in C on embedded devices for years and have written desktop apps to support them. First in VB6, then in C#.
I recently started making better use of classes for reusing code (and for instantiating more than one instance of the class in a program). For example, I "wrapped" a UART interface with some additional functionality so I can use the same code for multiple ports by creating an instance of the class for each one.
It is in a separate file, but still in the same program namespace, so when I want to reuse it, I have to copy the file and change the namespace to the new project.
I'm sure there's a way to create it such that I can just reference it like everything else with either a "using..." reference at the top of the program or with a "Project | References..." checkbox. But for the life of me I can't find a good learning journey for this.
Any direction would help.
You want to create your reuseable class in an assembly - this is the equivalent of a dll from your C experience.
To create an assembly, have a separate project of type assembly (instead of exe) . You can reference the assembly from other projects. If your project is in the same solution you can reference the project, otherwise you can reference the compiled assembly.
C# uses a packaging system called Nuget, so you can package your assemblies into "Nugets" which you host in a Nuget Server. You can then use tooling to discover and import these.
Please create a Class Library project and include your class into that project. Make sure your class is public. Once you build this project you'll get an assembly which can be referenced from other projects. See Tutorial: Create a .NET class library using Visual Studio
There are different ways of referencing it.
You can have the class library project in the same solution as the main project. In this case you should add a project reference.
You can copy the compiled *.dll file to some folder in your solution (e.g. Lib) and add an assembly reference.
If this assembly is to be used in multiple projects please consider creating a NuGet package with this library and pushing it to some repository. Then other projects can add a package reference to this package.
Details:
How to: Add or remove references by using the Reference Manager
Install and manage packages in Visual Studio using the NuGet Package Manager
It is in a separate file, but still in the same program namespace, so when I want to reuse it, I have to copy the file and change the namespace to the new project.
Well, it isn't the best practice but (unfortunatly) still a common behavior. So don't worry to much about it.
What you could do to improve it place the file (and other reusable parts) in a seperated csproj.
For example name the project of the type class library and name it VinDag.Tools. Within the project create a folder UART and place the wrapper there. The namespace of the wrapper would then be VinDag.Tools.UART.
From know on you can just reference the class library instead of renaming the file. It's not necessarily required to be the same namespace as the project.
From there you can start considering (private) nugets. This would prevent you from copying files/csproj around.

.NET custom dependencies (no nuget)

So, I'm having trouble adding a git project to my net Core solution, and after spending hours trying to figure this out and being uncapable of finding a solution online, I decided to ask here.
I have a forked github repo (link) in which I modified some files to suit my needs, but I simply can't seem to get it to work with my current project.
The problem I'm having is that normally, when I want a package for a .NET project, I usually simply go to nuget and fetch the necessary dependencies. This is usually very simple and straight forward. But now that I have these modified files, I'm unsure on how to proceed.
I have tried adding it as a submodule, but after I built the project, I got an exception saying that the dll could not be found.
Then I've tried adding the dll itself as a reference, but the ImGui.dll depends on a C dll which couldn't be found then (nor added to the project).
Finally, I've tried adding the csproj as a project of my solution, but that didn't work either
Do you know what am I doing wrong here? Am I missing a key piece or is it just something obvious I'm not seeing? It can't be this hard to get it to work
From the look of it, that repository produces a DLL (output type Class Library). So modify it to your liking, and use the sample program build (ImGui.NET.SampleProgram) to test your changes. Once you're happy, build the DLL project (ImGui.NET) and use the resulting DLL as a Reference in your own app.
In Visual Studio:
Solution Explorer>YourApp>References>Right Click>Add Reference...>Locate your DLL
This means you should also keep track of your modifications to the ImGui.NET project itself, since you may/will be required to maintain this in the future.
Hope this gets you started -- update your question with more specific issues once you're underway.
Edit:
Like #CoolBots mentions, I probably misread your question. Seems like the build depends on cimgui.dll, which you can hotlink from the ImGui repo along with your custom DLL. In fact, the demo app is using cimgui.dll, cimgui.dylib and cimgui.so. Regardless of linking method, you want the files to copy into your build folder. I don't believe subfolder /bin is necessary.
You can find all the cimgui dependencies for various operating systems in the ~/ImGui.NET/deps/cimgui folder.
The demo also utilizes NuGet packages Velrid and Velrid.StartupUtilities.
Depending on your own codebase, you may or may not require these NuGet packages along with the aforementioned class library.

Why are some nuget package references required by applications?

I have a question that has been bothering me for awhile. I ran across this problem a few years back when I was dealing with writing a generic logging wrapper around some hosted provider instances using log4net.
The idea was simple enough, I wanted to write a logging and metrics that hid all the implementation in a separate visual studio project so when you wanted to add any telemetry support to another application you could just include the project, new up an instance of the logger and start logging using generic calls. If you ever switched providers or tweak logging settings, it wouldn't require any changes to the host applications.
This creates a strong decoupling point, where the main application used an interface in a logging class library, but would know nothing about the packages or providers that the logging class library was using to do the real work.
When I did this and tried out using Loggly's nuget package and log4net, I found that the calling application had to have a ref to the nuget package or else the dependent assembly would not be copied to the build directory. At the time I just wrote this off as something odd that they Loggly engineers were doing. But I have since encountered the same behavior in some, but not all other packages. (DogstatsD doesn't have a problem, Raygun does, etc..)
I have noticed that some nuget packages in assemblies are automatically copied into the parent output directory, but when I look for the setting that controls this, I cannot find it.
I have written dozens of class libraries over the years, and I have never had a problem with 'chained dependency assemblies (a refs b, b refs c, etc.) resolving when I build. It only seems to be some nuget packages that are a problem.
How do I force nuget packages referenced by a class library project to copy into the build directory without an explicit reference in the application?
Ok, I figured this one out.
This is a problem only for the Log4Net & Loggly wrapper assembly combo in particular because it is referenced entirely at runtime. Log4net loads up its required log appenders at runtime, and because .net doesn't see a ref to the assembly at build time, it assumes that it isn't being used and omits copying the required assembly to the bin directory. The solution when you know this is simple, just write an empty dummy method in the referenced library that you can call in the main application. This will cause .net to include the assembly in the build.
While this problem is specific to the Log4net library, it could occur anywhere that you are using an assembly that is only used with runtime reflection.

TFS and Libraries not available in nuget

So we have a ASP.net MVC 4 solution that is composed of the 3 projects BusinessLibrary.UI, BusinessLbrary.Domain, BusinessLibrary.Tests
We use nuget to manage all of our libraries like json.net, entity, etc. But we also have some private libraries that we have added. What is the best way to manage of the private libraries we have. I would like to be able to have a new developer to get all the DLL's associated with this project when they start.
Ive read that I could create a library or lib folder, and then just reference the DLL's to there. But should that be checked in with the Project' s Source Control then? Would I only want to copy over the non-nuget private libraries. Is this the best way to go?
What is the standard practice for situations like this, how should I be storing my private libraries?
Personally, I create a dependencies folder at the solution level. I put all non-NuGet libraries that I reference there. When I add the reference, I'm sure to reference the assembly from the dependencies folder. Make sure you add the dependencies folder to Source Control.
That way any developer pulling down the solution from Source Control will automatically have the correct version of all of the dependencies.
Optionally you can install your own NuGet server and place your libraries there after successfull server build of those libraries
We create a library directory, add the assemblies there and use relative paths to reference them. We also check in this directory, so every team member immediately has the newest assemblies.
Another option would be to setup a private NuGet feed (such as MyGet) and publish your assemblies there as packages.
In our project we created lib folder for private dll's and checked in it to TFS along with source code. NuGet packages are added to TFS automatically.

"An assembly with the same simple name has already been imported" error without duplicate reference

I'm getting the following error:
error CS1704: An assembly with the same simple name
'Interop.xxx.dll, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null has already been imported. Try removing one of the
references or sign them to enable side-by-side.
Everything I've seen says that I am referencing two assemblies with the same name and I need to remove one of them. However, I've checked and I'm only referencing it once.
This also only happens when I'm using msbuild to build from the command line on my dev box. If I build through Visual Studio or do a clean build on our CI server I don't see this error.
I've tried completely removing all of my source and building from scratch to more closely resemble the build machine but no luck.
So it looks like I can't read today!
The project had a reference to the Interop and a COM reference that generated the "same" interop. So there were two and I just didn't search very well. I still don't understand why it worked in other places but this did fix it.
In the Error List window, the project that was triggering this error was listed in the Project column. I got around the error by doing the following:
I unloaded the listed project (right-click => Unload Project)
Opened the XML for edit (right-click the unloaded project => Edit {ProjectName.csproj}).
Searched for the offending .dll, and noticed it was listed multiple times in the XML
Removed the entire Reference tag related to the offending dll, and did so for every copy of the reference except the first one listed
The reason it was listed multiple times was because several referenced libraries used that dll. This shouldn't be a problem, in and of itself, so I'm not sure what caused this error to suddenly pop up for me. I'll update this answer if I figure that out.
In my case the duplicate entry was caused by a NuGet package reference and a direct file reference to the same assembly in the packages folder. I am not sure how the project got into this state, but unloading the project and searching the XML file for the offending assembly name resolved the issue for me.
Note that in my case this started happening after updating a NuGet package to a newer version with no other changes to the project, so this maybe caused by a bug in NuGet.
If this is a web project, are there any strong-named references to the other version there? Those won't show up as a project dependency, but will cause a run-time error like you describe. Hope that helps
I had this problem but in my case, I had an old copy placed in the current folder for the EXE loading my component, that was loaded together with the current one, that was loaded by hand from my projects folder. Deleting that old copy solved my problem.
I used Debug > Windows > Modules window to see which modules were loaded at that time and that solved my problem.
For others facing the same as me: if building via command line using property AssemblyName, it will overwrite all assemblies generated by all solution projects - in other words, you will end up with (N -1) assemblies named the same where N is the no. of projects - the startup one (which generally will generate an exe).
This happens because all build command line properties are global and overwrite any project-specific setting. See this and this.
From the msdn link mentioned above:
Global properties are properties that are set by using the
/property switch on the command line, or properties that are set by
the integrated development environment (IDE) before a project is
built. These global properties are applied to all projects that are
built by using this Engine.
In my specific case, where Jenkins is the CI tool, I ended up adding a windows batch command at the end to rename the .exe only to what I originally intended when passing the AssemblyName parameter.
For those developing UWP projects that have project references that include specifically the Microsoft.Windows.SDK.Contracts nuget package (or other dependencies that reference it), this is a common error when the version of the SDK contracts is targeting a different version of the runtime to how your project is configured.
For instance, when targeting Windows 10, version 1903:
Any dependencies or reference projects should target or at least support the same runtime version.
it is common thought process to update all NuGet packages when a new stable version is available, but this is not always a helpful practise on its own. Just because a new stable version of a package is available does not mean that you should or that you can easily use that version.
Even though this package for SDK contracts has a stable update, it is not compatible with my main project configuration, Nuget does not know this so it allows the update.
This package is specifically designed to provide windows dlls for project types that DO NOT have windows platform targeting support, it copies the same dlls that are included by the UWP targeting config. By installing later versions of the package the references from the satellite project will be included in the output along with those provided due to platform targeting, ultimately causing OPs error.
There are similar SDK and targeting packs for Windows IoT Device Runtimes, this information should help you identify and resolve those issues if you get stuck on this issue as my team often does :)
In my case, the issue was on wrong characters in the ProjectReference section of my csproj file.
Background
I have a project that references another library I maintain, which I publish as a NuGet package.
Whenever I make changes to my library, I usually reference the local dll in my project to test and make sure everything looks good before I publish the library as a NuGet package.
When testing, I just comment out the PackageReference line and uncomment the ProjectReference one so it references my local dll, like so:
<ProjectReference Include="..\..\my-class-library\MyClassLibrary.csproj" />
<!--<PackageReference="MyClassLibrary" Version="2.0.1"/>-->
Root cause
I had the slashes inverted, so I was using / rather than \ in the path, like so:
<ProjectReference Include="../../my-class-library/MyClassLibrary.csproj" />
Once corrected, the issue went away.
Try this instead: remove Interop.xx.dll from the reference section in Solution Explorer and Rebuild the project
In our case this error was shown when we had a duplicate reference inside the .csproj file (although I have no idea how this happened).
The difference to an already posted answer is that, in our case, one was a project reference and another one was direct binary reference to a dll.
Once we removed one of those, project correctly compiled.

Categories

Resources