How to use my DLL when it is not in the GAC - c#

If I have a Project which uses my own made .dll and this .dll is not registered with the GAC but simply in the same folder as my projects App. eg C:\Program Files (x86)\MyApp Folder.
Can I, and more importantly how do I properly reference this .dll if I want to for example build a second project which also uses this .dll. It is possible that I build a few small apps that will use this .dll.
In this case must I have it in the GAC or if it is not there what must I do?

If I have a Project...
You should never put yourself in a situation where you have just a project. You first and foremost have a solution. A collection of projects that, together, build an app. Projects of course have a dependency on each other, you use a project dependency to tell the compiler about. Which automatically takes care of reference assemblies, the output of one project becomes the reference of another. And any changes you make to the source code of such a project automatically propagate to the others.
This is usually as far as teams take it.
This however tends to not work so well on very large solutions with dozens of projects, Visual Studio tends to get sluggish and building can take a long time. An important step to take in such a case is to freeze a root project. A programmer needs to get an explicit permission to make changes to such a core project. Because such a change tends to be very destabilizing, requiring many changes in dependent projects. And effectively destroys many hours of testing and validation time.
You do this by explicitly removing a project from a solution. Which now automatically makes it difficult to make changes to it. The dependent projects need to be updated to use an explicit reference assembly instead of the project dependency. Picking a well-known location for the assembly is important. Either source control or (preferrably) a build server is instrumental to be the source of the assembly. A tool like Nuget can be very useful.

Related

How can I save disk space when building large number of projects and solutions?

I'm working on a large enterprise .NET software. Currently the code is organized in 400+ projects grouped in almost 50 solutions. The folder structure containing code and other artifacts is about 9GB, but after the product is built, it consumes about 70GB. This is becoming an issue for developers because they normally work on different versions of the product and each one is consuming the same amount of disk space.
The main reason for this waste of space is because the build process is producing a very large set of copies of the same assembly even where it is not strictly necessary. Basically every intermediate class library project contains all the dependencies assemblies in its bin folder, where they are not needed at runtime.
For dependencies:
within the same solution we use project references
across solutions we use assembly references
for third parties components we use package references
I know that I could avoid copying dependencies in output bin folder (e.g. using CopyLocal=false or equivalent for project references and package references) but in this way, when a project is consuming an assembly in another solution, transitive dependencies are not copied even when they are really needed (for example when the project is an executable). This is causing issues at runtime or during unit test execution.
I tried to replace all assembly references with project references, even when the project is in another solution. In this way, I noticed that dependencies are correctly managed and transitive dependencies get copied properly. However, I'm a little bit scared of using this approach since it seems not natively supported by the IDE: in fact Visual Studio does not allow you to add a project reference to a project that is not in the current solution. My fear is that developer will have glitches in the IDE if I change dependencies in this way.
Do you have any suggestion or similar experience? The goal would be to minimize the number of copies of the same assembly across all projects and limit them to the minimum in order to reduce the disk space requirement.
I tried to replace all assembly references with project references, even when the project is in another solution. In this way, I noticed that dependencies are correctly managed and transitive dependencies get copied properly.
This is the way I would tackle this, especially since it seems to be working for you. However, as you've discovered, this means everything will need to be in a single solution. Enter filtered solutions.
Take Microsoft's lead, for example. In the dotnet/aspnetcore repository, they have 562 csproj files. However, instead of breaking these projects apart into separate solutions, they have a single solution in the root that contains everything, AspNetCore.sln.
Obviously having a single solution that large isn't going to play very well with the IDE. To solve this problem, Microsoft introduced filtered solutions in Visual Studio 2019. This feature basically provides a way of specifying a subset of projects in the solution to load. This allows teams working on entirely separate aspects of the same solution to be able to load only the projects they need.

How to force visual studio to check for broken file references at compile time

This question is specifically about file references
My project has a reference to library A. Library A has a reference to library B.
If I don't add a direct reference to library B, the project will compile fine, but then throw a "could not load file or assembly B" exception at runtime when it tries to load library A.
So, how do I force visual studio to check for all broken file references at compile time? Alternatively, is there any other way to find these broken references (a tool, VS extension, etc.)
Here's an example project that reproduces the behavior.
https://github.com/RaikolAmaro/BrokenDependencies
This isn't a compile-time problem, as, at compile time, all required references were present and accounted for. Otherwise, it wouldn't have compiled in the first place.
It's a runtime problem and Visual Studio doesn't care much about what you want to have in the output directory or not. This is why you have total control over which elements you want copied from NuGet packages as well as other projects. Why? Because you may be using a installer or packaging solution or have some magic assembly resolving code to find your dependencies. You may be relying on plugins or configuration based dependency injection. Too many things which will thwart a scan like this.
There is another problem. While an assembly may depend on a certain other assembly, your code may not require it. It that's she case, if your code never loads a codepath that requires this other assembly, then you don't need it in your output directory to run.
There are tools that scan all the codepaths in your projects, the assemblies they depend on and so forth. These can be used to see whether you have all the required binaries to run the code.
http://www.dependencywalker.com/
There is problem with these tools. The same problems mentioned above. If you use dependency injection through configuration or convention (e.g. based on reflection) or do your own reflection, or depend on the dynamic keyword, then these tools may not be able to find all codepaths you depend on and may require some configuration or in-source annotation to figure that out while scanning.

Reference all required assemblies for runtime or compile time?

I thought this would have been a question already asked many times, but I can't find it.
We are developing applications and have multiple shared assemblies which are used by multiple targets. When I'm creating a new application I'll probably use such a assembly (eg Framework) and reference it in my project. All fine here. However, when this Framework assembly uses for example the Model assembly, I'm not forced by Visual Studio to reference it. As long as my code doesn't touch any Model types, it will compile fine without a reference.
At runtime, it does require the Model assembly. When releasing this application there is no problem, as I just include all the required references in my installer project.
The problem arrizes when I try to debug the application. The bin folder won't have the Model assembly as it's not referenced.
The question
Is there a best practice to solve this "reference of a reference" situation?
Solutions we've come up with
Add the Model as a reference
This feels wrong, we pollute the project
Include the Model project in the solution and add as project reference
This feels even worse (polluting the solution)
Add post-build step
Could be a solution, but doesn't feel that right either.
The best solution for this is to package your Framework or Library assemblies (or sets) with NuGet. You can then use NuGet in Visual Studio to take care of all these references. This works great, even when using nested dependencies.
NuGet is fully supported and integrated into Visual Studio. It is very easy to host your own package repository (that can be as simple as pointing to a file share with packages).
You can host a private on-site repository for your own (internal) pacakges. That's what most shops do. You can combine that with one or more public NuGet repositories for public things as Log4Net etc..
And while it may seem to take some time to get this up and running (which is relative, try to just use a public package first just to get the hang of using NuGet first), you get a whole lot of benefits as well. For example, you get support for versioning your libraries out of the box.
At my company we've had this problem for years, and we used to build and check-in library assemblies (50+) into source control, and dragging that around across branches. Since we've switched out approach to using NuGet, this problem just gone away for us. Never looking back to that anymore.
A reference to another project does not necessarily need to be a Project reference. In your example, reference Model as a Bin reference within Framework. This way a pre-built Model will be included with the build of Framework.

Console project and winforms project in the same solution

I have a winforms that gathers information from users and updates some SQL-Server tables.
I have a console which runs on a remote server and is scanning the same tables; given certain criteria in the tables this console completes several processes.
Currently the console and winforms do not need to talk to each other.
Should I place both projects in the same Solution or in two separate Solutions?
Use single solution. For more info you should read this (section Partitioning Solutions and Projects)
Advantages
The single solution model offers the following advantages:
When you need to reference another assembly generated by a separate
project, you can use a project reference. Project references are the
preferred way to establish references to other assemblies and they
are guaranteed to work on all development workstations in a team
environment. The many advantages of project references and guidance
on when to use file references are discussed in Referencing
Assemblies in Chapter 4, "Managing Dependencies."
Assembly versioning issues are avoided, because Visual Studio .NET
detects when a client of a referenced assembly needs to be rebuilt.
Project references are sensitive to changes in the configuration of
the referenced project. This means that you can automatically switch
from Debug and Release builds across projects without having to reset
references.
The system build process and build script is much simpler.
Disadvantages
You are advised to adopt the single solution model whenever possible. However:
The model scales only so far. If you want to work on a single project within the solution, you are forced to acquire all of the source code for all projects within the solution.
Even minor (nonbreaking) changes to a single source file within a single project can result in a rebuild of many projects within the solution, due to project dependencies. If an assembly's interface changes within a referenced project, you want the client project to be rebuilt. However, unnecessary rebuilds can be very time consuming, especially for solutions containing many projects.

Visual Studio : How to manage code shared between projects

This has probably been posted before, but I'm not sure what search terms to look for!
Quick explanation.
I have code that is shared between a few projects. This code is still work-in-progress itself. The issue is that whenever I need to update this code for whatever, I don't want to have to do it 3 times, this will become a nightmare.
Is there a way to add it to a project, without copying it into the project folder?
i.e. I want the shared class to be linked into my 3 projects as
C:\code repository\sharedclass.cs NOT \eachproject\bin\sharedclass.cs
Do I have to create it as it's own library project? It would be much better if the compiler could compile it as 'external' code.
Cheers.
As others have said, you can simply right-click on your solution in the solution explorer, select Add > Existing Project, and browse to the common project's .csproj file, and it will be included in the solution from its original location.
There are two problems with this however, which may or may not be an issue, depending on the size of your team:
The common project will be included in each solution with a relative path to the solution file (i.e.: ...\CommonProject\Common.csproj). This means all developers have to have the same working file structure or they will get errors when they try to open the main project.
In the scenario that the common project is referenced by multiple projects (say two - A and B) and a developer working on project A has to make changes to the common project as part of their task, there is no way for that developer to know if the changes they have made will break project B without them actually checking out project B and compiling it. As more and more projects reference the common project, the risk of this happening increases to the point where it becomes unmanageable.
Again, as others have said, there is no 'correct' way to do this. However, the approach I have taken is as follows:
Use continuous integration such as Cruise Control to manage the building of the projects and put the common project as a standalone project on the server.
Create a directory under your source control to house built common DLLs. Have this directory checked out on your build machine and whenever the common project builds, it copies the output DLL into the DLL folder and commits these changes to source control.
Use environment variables on all developers' machines and the build server to control the location of the common DLL folder and reference the DLLs using that variable rather than the hard-coded path. (i.e.: rather than C:\Source\MyCommonProjectDLLS\Common.dll, use $(MyCommonLocation)\Common.dll with the variable 'MyCommonLocation' set to C:\Source\MyCommonProjectDLLS)
For any project which references the common DLL, set up a CI trigger on the build server for that project to watch the common DLL folder. Whenever changes are committed to it, the build server should then build all consuming projects.
This immediately lets you know if you are committing breaking changes for any other project. The only drawback is that, in this model, consuming projects are forced to take updates to the common DLL as soon as they are made. An alternative is to version the Common DLL from the source control revision when it is built, and place each version in its own sub directory under the common DLL folder. So you would end up with:
Common DLLs
-1.0.0.1234
-1.0.0.1235
-1.0.0.1236
And so on. The advantage of this is that each project can then choose when to take updates to the common DLL by simply referencing the new version of the code. However, it cuts both ways as this can mean that some projects are left with older versions of the common code for longer than they should, which can increase the work involved when the time comes to finally bring in those changes.
Yes.
You can add a project from anywhere on your hard drive to a solution. So put the shared code into a class library and add that to your three projects.
Microsoft has been supporting an open source project which comes built into VS now, its called NuGet, you can output your shared project as a nuget file and consume it in your other projects.
It will actually deploy all the files you specify in the package upon build.
This is how .Net supports dependencies now. You will notice that even things like EF come through NuGet packages. You can even host it for free on places like MyGet.org I use this and it works quite well.
http://nuget.org/
I use git submodules to achieve this.
Create a new git repository for each module (project) that you want to share between solutions. I usually also include unit tests for that project in a separate project but in the same git repository.
Add a submodule to the git repository of the solution that will use the shared code. Adding a submodule creates a link to a specific commit of an external repository. When the code in the submodule is updated you will be able to pull the updates to your parent solution, which is essentially the same as updating the reference to the submodule commit. I find that the process is easier to visualise using an app like SourceTree.
Adding the submodule and pulling the latest commit will create a copy of the shared project inside the parent solution folder. Import the project into the parent Visual Studio solution by right-clicking on the solution and selecting "Add existing project".
Add a reference to the shared project in the other projects that will be using it by right-clicking on the project and selecting "Add Reference" and finding the shared project in the "Solution" tab.
Now that the shared project is included in the solution you will be able to push and pull changes to the submodule and these changes will automatically be incorporated into the solution. You will also be able to see the changes in other git repositories that reference the submodule.
Yes, put the code which need to be shared in a separate class library project, build it and reference the DLL created from this build into your other projects.
It is better to extract common part into a separate project library and add reference of this project to all the solutions/dependent projects.
Otherwise you can Add code/file/item as Link.

Categories