Managing shared binary dependencies for multiple solutions - c#

Ok we have a number of solutions all with a lot of shared binaries:
what we do is the following.
In a shared drive we have this following layout where there is a directory for every binary dependency and a sub directory for every version
BinaryDep1
-----------Volatile
-----------1.0
-----------1.1
-----------1.2
BinaryDep3
-----------Volatile
-----------1.0
-----------1.1
-----------2.2
BinaryDep3
-----------Volatile
-----------1.0
-----------1.1
-----------1.2
In our solutions we have a XML file that lists out all of the dependencies and versions. We have a script that then goes tothe shared drive and download the dependencies into a sub folder of a solution called /ext
This works very well but has a few flaws that we are looking to improve and i wanted to get people's feedback.
We have many solutions so if they all depend on the same version of a binary dependency then we get one copy per solution (as its supposed to be self contained). So if i have 5 solutions that all depend on Syncfusion, i get 5 copies of syncfusion on my desktop. The two issues here are 1) slow download time (5x more than i need to) and takes up lots of disk space.
We like the model where have a local sub directory per solution with /ext so we never have to change project references but these seem like competing forces.
any ideas on how to normalize teh download so we are not downloading 5x the data and same the disk size without having to go to manually updating project references where i have to change reference in VS for every version upgrade.

What about the same struture in all developer machines?
Like:
d:/projects
d:/projects/ext (the shared libraries you need here)
d:/projects/project1
d:/projects/project2
d:/projects/project3
d:/projects/project4
...
ps: I love conventions.

You may want to have a look at DEVPATH.
Other StackOverflow reference : Support for DEVPATH

Is any reason for not putting shared assemblies to GAC?

Related

How to get access to the files stored on another repository in code

I want to get the access (read) files with text which located on another repository. Is it possible to do at all?
We faced the problem of preserving the history of big files if we place them in the same repo. For every commit it saves another copy of these files in History, which leads to very understandable issues. So we decided to create another repo and store them there. But I have noe exp how can I access it from the code inside the current solution.
I'd be nice to get the filePath of this files in currect solution, so can read them and process.
If you want to reference something, it either needs to be placed alongside your project, or you need a build step that retrieves it and places it somewhere your project can reference.
If these are actual text files you're wanting to read at runtime, those text files need to be discoverable by some means... The fact they're in another repository doesn't help, because that's just another file path that you aren't aware of.
I'd recommend building/publishing your other repository to some discoverable location that your main project can reference at build time or run time.
You can use git clone operation, and just download files to your project. In your main project add rules to .gitingnore to skip those big files from main repo.
You should take a step back and revisit the original problem - large files bogging down the repo. As I noted in comments, what you say (that each such file is copied in every commit) is not accurate; but it is true that large files - especially large binary files - can cause problems in git repos.
And the standard tool to solve those problems is LFS. This creates a separate "LFS repo" and manages its relationship to the base repo automatically, which means questions about how to manually read files from a different repo can be avoided entirely.

Changing structure within a TFS solution in active projects?

We have a solution containing about 30 projects that is ogranized in a given catalog structure(in the solution). On the filesystem the projects is however located all around the place so now I need to clean this up. There is however several problems with this :
If I move a project on the filesystem it will be unavailable in the solution, to solve this I will have to remove the project and then add existing to the solution. Im not sure how this will effect the TFS history that most not get lost?
There is people working ont these projects and if thay are moved when checking in there will probably be big problems?
So how do I solve this changes without stalling any other development within this solution?
You need to do it quickly, or at least each action should be quick.
If you need to move a Project to the correct location you should:
Notify all developers you are moving a project and not to check out.
Move the Project folder
Open the Solution file in notepad and change the location reference to the project
Save and checkin.
Instruct all other users to get latest.
Do that for each move, slowly over a few days and you should be good. A big bang move is also possible but if you have 50 Devs then it is costly.
I had to do the same thing.
Our Solutions were and are organized in this way:
TeamProject
App1
DevFolder (contains branches of BranchTest)
BranchOfDev1
BranchOfDev2
BranchOfDev3
BranchOfDev4
TestFolder
BranchTest
ProdFolder (contains branches of BranchTest)
BranchProdV1
BranchProdV2
BranchProdV3
App2
Dev...
Test...
Prod...
...
This is just one solution with several dependencies on existing Projects in other Folders/branches etc..
Everything branches from the TestBranch. Devs Merge into Test, ProdVersions are branched from Test.
The TestBranch contains the newest Version of the application
The devs only develop in their own dev-branches and when they are done they merge to the TestBranch
I did the move in this way:
Create a New Team Project in TFS
Create the new structure according to the existing one (the branch-concept is ok)
DEV-STOP. Everybody must Merge into the TestBranch
At one point moved the TestBranch to the new Location.
Moved all dependencies as well
Edited the .sln by Hand with the new Locations of dependencies, check that in (answer to your question)
DELETE all the DevBranches
Create new DevBranches in the new structure
Everybody deletes their local Workspace, redownload from the new TeamProject
Cloak the old Folders. DO NOT DELETE them if you want to Keep the history!
Everybody should be happy now
Edit: We are now in the process of creating nuget packages for all the external and common dependencies. This way in the future we'll be able to update the core/dependencies without breaking anything that uses earlier Versions of them.

Partially reference a DLL

I have a library DLL full with sort algorithmn, parsers, validators, converters etc. The DLL is about 40 Mb (that is not much I know but still). Now I would like to reference just the parsers of that DLL. The point is to get out those parsers without shipping 40 Mb to the customer.
Is there a way everytime I make a release build to just take those up-to-date parsers from my library, store them into some kind of .partialDll file and deliver only them to the customer? The result would be me keeping all my helper classes in one big library which keeps growing and the customers get just what they ordered..
I guess I would need to deal with alot of reflection to achieve something like this, right? Any ideas?
Let me start with a quote from MSDN:
"Assemblies are the building blocks of .NET Framework applications; they form the fundamental unit of deployment […]."
Note that the quote is about assemblies, not about DLLs. There's a difference!
Although most .NET assemblies consist of exactly one DLL file, that is not a strict requirement: An assembly can in fact consist of more than one file; such a "multi-file assembly" can, for instance, consist of several DLLs, which in turn are called "netmodules". (A netmodule might have a .netmodule file extension by convention, but it's really a DLL containing .NET metadata and bytecode.) Each multi-file assembly has exactly one "main" module which carries the metadata that references all the other assembly files and so ties them together into a logical whole.
While an assembly has to be deployed in full (as per the above quote), the .NET runtime can load only those netmodules that are actually required for JIT code compilation and execution.
So you can split up an assembly into several parts, and have the runtime load only what is actually needed; but you cannot do the same to a netmodule / DLL file. A DLL file can only be deployed and loaded in its entirety.
Note also that Visual Studio's support for netmodules is non-existent for all practical purposes, so most people don't use them, which is why you see so few multi-file assemblies in the real world.
The bottom line is this: In practice, if you or your clients are interested in only a part of an assembly ("DLL"), then it's usually easier to split a large assembly (that is, one large Visual Studio project) into several inter-dependent assemblies (several smaller Visual Studio projects).
In general, no, there is no way to achieve that. Once you pack "everything" into a module and compile it, you can't split that module later into smaller ones. (well, ok, you can analyze the bytecode and rewrite the assembly, see the end of this post).
For me, your nullhypothesis seems wrong. You don't need to work with "one huge library that keeps all your helper classes", and really, you dont want, or you will not want to either. If you don't feel like that, I assure you that in time, years maybe, you will hate such one-to-have-it-all approach.
This is exactly what you want to escape from and this is why .Net and many other languages/environments support concept of "libraries" or "modules" and allow you to use multiple of them, and that's why most of the projects you see everywhere aren't created as "one huge EXE". It's much easier to reuse, analyze and even hunt bugs when you have it in smaller chunks.
--
However, if you'd insist, there are ways (ugly) to achive something-like you think. I assume that the "huge DLL" is in C# and is controlled by you.
First, somewhat naiive but working way, is to use "file links". In VisualStudio you can have a project that contains tons of files and producess a BigDLL "all.dll", and just by its side you can create another project that will not contain any files at all, but that will contain links to the first projects' files. Use typical "Add a file.." option to a project and note that near the final "Add" button there's a down arrow that expands to "Add as link..".
This will cause the file to stay in HugeProject, but the SmallProject will see the file too and when SmallProject is compiled, it will pull the code from that file too.
Note that this way you will actually build two separate modules assemblies: big one and small one, and your final product will need to reference the small one.
This way is naiive and ugly, it is just as if you manually copied/splitted the huge project into smaller ones, but with the tiny advantage is that you don't need to copy the code files around.
--
intermission for side-thoughts:
you can use #if to conditionally turn off some currently-unused code, however setting the flags that drive those IFs will be cumbersome
you can edit .csproj files and use MSBuild conditional clauses to automatically exclude unused code files from your HugeProject during final builds, however setting the flags that drive those IFs will be cumbersome too
--
The second way is to keep everything in the HugeProject, and to have your application(s) reference it directly, and then after building and testing everything, just before packing that and sending to customer - use some kind of trimming utility that will check what parts of code are referenced and that will remove all dead code from the assemblies. I can't give you any name for such utility, but many obfuscators come with such feature.
They will run through your compiled code, cross-reference everything, change/remove/trash class/method/propertynames and also they may as a bonus remove unused bits. Then, they'll write mangled assemblies back to disk ensuring that they reference each other and not the original ones from before mangling.
example: See a question related to that
example: See an example of such utility also consider ILMerge for better results.
Cons - utility may leave some trash it couldn't decide whether it is used or not, finding/testing/buying it may take some time and resources, you can have some signing problems since the stripped-assembly will be a brand new assembly, etc. Also, such utilities have problems if you invoke some code only by reflection and it may require you to provide some extra hints or to make sure the code "seems to be used" (example: a whole namespace of "plugins" that implement "IPlugin" and then your app searched that NS for Types and uses Activator.CreateInstance to instantiate them; no hard-linked usages, trimmer may decide to remove all plugins as "unused"; you'll need to configure trimmer carefully or be suprised).
Probably a few other ways could be found too, but seriously, in most of the times, you don't want to waste your time on that, especially manually. So just tidy up your code and split it into small libs, or start looking for automatic obfuscator&trimmer.

Compare (and merge) two VS C# projects

I have two VS C# projects (specifically, for an Outlook plugin) that I believe to be very similar with the exception of perhaps 100 lines of code. I'm slightly worried that there might be other configuration options for the project that are different, so I'd like to compare those two.
What is the best way to see the differences between the two codebases?
I've tried putting the two projects in parallel directories and using diff, but since the projects are named differently, some of the files don't match up. I'm just wondering if there's an easier way to do this?
It sounds like you need something like WinMerge to go through and point out the differences between the two projects. It's free, and I know you can compare folder contents with WinMerge, so that's probably a good place to start. Run WinMerge on the project folders and it should generate a detailed comparison outlining the differences between the files.
See this tutorial on comparing folders:
http://manual.winmerge.org/CompareDirs.html
I strongly recommend Code Compare (not affiliated, just a happy user) for this kind of job - there is a free version and a more advanced commercial version.
It integrates nicely with VS and has syntax highlighting for C#, C/C++ etc.
One way: Make copies of both projects, rename the files and folders in one to match the files and folders in the other, then use your favorite folder compare tool to compare the two.
This won't help you unless there was a true copy-and-paste relationship between the two projects.
The better way would be to use refactoring. After creating unit tests for both projects and achieving an adequate level of code coverage, go class by class and method by method using refactoring to try to make pairs of methods identical. You may then identify methods that should be pulled into base classes or moved into other classes.
Eventually, you may find pairs of classes which are identical. Move those classes into a common library, then rename all uses of one of the classes to be a use of the other. Then delete the one no longer used.
Repeat until there is no more duplication.
If you've got modifications like renames or partial code moves, importing both versions into a single git repository (as two different commits of a single directory) could help. Git tracks contents of files, not the files themselves, so it is possible to find out e.g. a function that has been moved from one file to another.

Reading from a file inside a VS solution

I have an xml file that I want to include along with my program as a template. I would prefer that it be bundled with the .exe when the project is completed.
Is this possible?
If so, how should I reference it in the code? I would assume that referencing "myXML.xml" won't work because, if it is included, the file no longer exists as a standalone object.
An alternative idea is to copy/paste the contents into string, but that seems like a bad idea in so many ways. (It's 900 lines.)
Ideas?
Thank you.
The real motivation behind this is I really prefer standalone executables rather than making the user go through the installation process. Additionally there's the extra benefit that they're less likely to f- it up.
This is quite simple to do, you can store files in any .NET assembly as "Embedded Resources", which can be then accessed at runtime.
See the Microsoft article here for a detailed rundown on how to do this.
Another way is resource files, http://msdn.microsoft.com/en-us/library/7k989cfy%28v=vs.80%29.aspx

Categories