In a quest to reduce the dependencies in my projects, I now have everything depending on and implementing interfaces, and they are glued together by an IoC container. This means projects need only to have direct references to such interface libraries.
However, if you don't specify the project as having a reference to the implementation (even though you don't need it at compile time) the implementation libraries are not included with the executable or in the setup project.
Is in a way Visual Studio promoting bad practices by requiring explicit references when they are not needed? Is it possible to have the dependencies only to the required interfaces and in this case what is the best method to get the implementation libraries available?
Is in a way Visual Studio promoting bad practices by requiring explicit references when they are not needed?
Not really. Your issue is one of deployment, not building.
Deploying an application and building it are separate things - if you have a good deployment strategy, you will be deploying implementations where they belong.
Is it possible to have the dependencies only to the required interfaces and in this case what is the best method to get the implementation libraries available?
The easiest way is indeed to reference the implementation assemblies. This will definitely make building and running locally as easy as F5, but do you really want that? To be honest, if you and your team have the discipline to only code to interfaces, that's all you need (and there are static analysis tools like nDepend that help with ensuring that remains the case).
One way forward is to create a deployment script that will deploy all dependencies whether local or elsewhere.
Visual studio does not require these references, but your IoC container does.
When adding a reference to the project, its binaries are automatically included in the output folder, which is necessary for your IoC container to glue the code together. There are other ways to get these binaries to the output folder than referencing their projects in Visual Studio - perhaps a post-build step?
No. It is simply the minimum they need to do in order to give developers working code without them having to do anything extra (aside from hitting F5) or for all references to be added by default (which would likely be a mess and slow on older hard discs.
For local development builds, you can simply have a post-build step on the relevant project to copy the DLLs to the main working directory. Just make sure the project is added to the active configuration to be built, other wise you'll go through a whole annoying debug session on the post-build only to realise there was no-build... lol
VS 2010. Post-build. Copy files in to multiple directories/multiple output path
Copy bin files on to Physical file location on Post Build event in VS2010
For full-scale application deployment, you'd likely be looking at Visual Studio setup projects at a bare minimum, but more ideally something like WiX or another deployment tool-set.
Related
I have a large solution currently under VS2010, with lots of projects and dependencies. Some of them are installed to the GAC, some of them are just included from a "lib" folder. I need to build one of my projects (specifically a WinForms app) to able to run on any, non-development computers without any installation process (except for the .NET runtime of course), just as portable apps do.
For this to work, I need to have all of the referenced DLLs and their whole dependency tree in the output folder of my EXE. I can do it for exemple by marking the dependencies to "Copy local" in the properties window, but that works only for the direct references of the EXE project, so it's far not enough. Another way is to make a setup project, but my client and also I want to avoid that (in the final version I'm gonna use ClickOnce). Of course I can always do it purely by hand, gathering all the DLLs manually, but that's quite a nightmare.
Is there some tool, msbuild trick, command-line option, whatever hack to force Visual Studio to gather the whole dependency tree of my EXE during build, and copy them to the output folder? So that I could just ZIP everything together and send to my client.
I actually chose a somewhat "middle" solution, the following way.
I created a "dummy" setup project, not caring about setting anything but adding the project outputs (primary output, localized resources, contents, etc.). It was a 2 minute task this way.
I built the setup project, and got the MSI file as the output.
I've extracted the contents of the MSI file to a specific folder, called "MyAppPortable" for example. I found the solution here. The command-line command is
msiexec /a "absolute_path_to_my_MSI_output" /qb TARGETDIR="absolute_path_to_my_desired_output_folder"
I got the full application with all of its resolved dependencies (except for late-binding dependencies, but I took care of them manually, by adding them as references to my projects). I could ZIP the whole folder, put it on another computer, and voila, everything worked fine.
Basically, using Visual Studio, you can set all of your Solution's Projects to build into the same Output folder and use this folder as your Windows Form application folder (where the application EXE will reside).
By doing this, you will coordinate all of the possible assemblies references that your app is depend on.
In VS 2012, right-click on a Project => Properties => Select Build (left pane) => Set your Output path:
I would select a a solution-level folder as the Output path.
And if it's prohibited to perform such a modification at your workplace so I would suggest you to use dependency analysis tools like the following in order to interrogate and gather the appropriate assemblies that your app is depend on and will require at run-time:
Dependency Walker
NDepend
Red-Gate Reflector
Update:
Using the above mentioned tools will not yields assemblies references which are late-bounded (at run-time), for this case you may use: Fusion (the Assembly Binding Log Viewer)
Check out the Fody/Costura recommendation from this question:
Embedding DLLs in a compiled executable
It's great! I just tried it out for a similar need and in less then a few minutes I had a completely portable (except the .Net framework) exe that I could easily give to co-workers.
So I have a solution which contains 4 projects, a "Core" Project which is the actual application (as a class library), and 3 wrapper projects, "Console", "WinForm" and "Service" which basically wraps a Facade class in the core class and contains various settings to handle different logging strategies for each different application (Console/Trace/File) and launch the application as either a Console, WinForms or Service, depending on how the customer wishes to deploy the application.
In the Core project I have 3 resource files which contain simple template views for the Nancy web framework. However the way Nancy looks for these views are on the current path. Since the files in the Core project aren't on the current path for any of the 3 other projects I need a simple way to access these files across projects.
Somewhat naively I thought this was where the concept of a "Solution" came in, to handle dependencies between projects. However by searching the Internet, much to my surprise, it appears there is no elegant way to do this. The only two solutions I've been able to find involves copying the files to a scratch/temporary or directory in the solution, and copying them to the respective needed directories later, as post build actions, and Adding an item manually using "Add as Link". Now while both these solutions technically work, the first leaves (possibly out-of-date) build artefacts lying about where they don't really belong (IMHO), and the second is tedious, time-consuming and prone to human error (because you can't just link to a directory).
Are these really my only two options, or is there some third, totally obvious way I've just missed because I'm new to Visual Studio?
You could use a custom IRootPathProvider in Nancy, if the only things you need are Nancy specific.
The other option is to link a folder - you can do this, but it involves manually hacking on the csproj file, there's a few questions on here about it, including this one:
Visual Studio Linked Files Directory Structure
Nuget is a package management system, that I have used to share artifacts between projects as dependencies. You could include libraries available via nuget.org or have your own nuget packages defined.
Teamcity has got good support for generating nuget packages with every build and can serve as a Nuget server.
Here is a reference to include files into a nuget package.
Like most shops we've got a team of people working on various projects that all need to access the same core information and functions that relate to our business, usually in C#. We're currently just copying common classes from project to project, but everyone is starting to have their own flavors and we want to consolidate.
We use Tortoise SVN and have decided to maintain a separate project to contain our common classes, but are not sure the best way to deploy this common code to our various applications. We work for an internal IT shop that can dictate everything about how the users access the applications, we don't have to worry about releasing our products into the real world.
Some of our thoughts have been:
Compile the classes into a single DLL and load it into the Global Assembly Cache (GAC)
Compile the classes into a single DLL and save it to a centrally located shared drive to be referenced by all other projects
Compile the classes into a single DLL and include it in each project
Just fetch the most recent classes when starting a project, but don't have a central shared library (our interpretation of this: http://www.yosefk.com/blog/redundancy-vs-dependencies-which-is-worse.html)
SVN Externals http://svnbook.red-bean.com/en/1.0/ch07s03.html
I know this is a common problem, and if you spend any time looking into these or other options, you invariably find people explaining the pitfalls of each method (versioning, regression testing, "DLL Hell", "The GAC sucks", etc). I can hardly find anyone talking about what WORKS and why. Is there a preferred method?
At my company we have the same issue. Currently, we just use .bat files that go to our SVN Trunk and pull the most recent .dll references and fill a local References folder for the project you are working on.
However, we are currently working on switching this system over to NuGet. I'm not 100% sure how it works, but it's definitely worth looking into. Looks like you can set it up to where you can point it to a shared code repository, and then in Visual Studio using a plugin, it's as simple as just right clicking and hitting 'Update' everytime you need to get the newest code.
we have a number of c# projects that all depend on a common DLL (also c#). this DLL changes somewhat frequency as we're in an environment where we need to be able to build and deploy updated code frequently. the problem with this is, if one of these updates requires a change to the common DLL, we end up with several client apps that all have slightly different versions of the DLL.
we're trying to figure out how to improve this setup, so we can guarantee that anyone can check out a project (we use SVN) and be able to build it without issue. it seems like tagging each and every DLL change to a new version is excessive, but I'm not sure what the "right" solution is (or at least something elegant).
it would be ideal if any solution allowed a developer to be able to step into the DLL code from visual studio, which only seems to be possible if you have the project itself on your machine (might be wrong there).
Frankly, I think versioning your DLL in source control is the RIGHT solution.
It's very possible that a quickly changing core DLL could cause binary and source compatibility in a client project. By versioning, you can prevent each project from using the new DLL until you're ready to migrate.
This provides a level of safety - you know you won't break a client's project because somebody else changed something underneath you, but it's very easy to upgrade at any time to the new version.
Versioning in SVN is trivial - so I wouldn't let this be an issue. It's also safer from a business perspective, since you have a very clear "paper trail" of what version was used with a given deliverable of a client project, which has many benefits in terms of billing, tracking, testability, etc.
There's no easy solution - and the previous two answers are possibly the more accepted method of achieving what you want. If you had a CI environment, and were able to roll out all of your apps on-demand from a store that was built via CI, then you could avoid this problem. That can be lofty ambition, though, if there are old apps in there not governed by tests etc.
If your application is .Net 3.5 (might even need the SP1 too) then did you know that assemblies that are loaded from the network now no longer have any trust restrictions? This means that you could configure an assembly path on the machines in question to point to a shared, highly available, network location - and have all of your apps locate the assembly from there.
An alternative to this, but which would achieve the same goal, would be to build a component that hooks into the AppDomain.CurrentDomain.AssemblyResolve event - which is fired whenever the runtime can't auto-discover an assembly - and do a manual search in that network location for the dll in question (if you were to take the AssemblyName portion of the Full Name, append .dll to it, then you'd be reproducing the same search that the .Net Fusion binder performs anyway).
Just a thought ;)
I think you could benefit from setting up a continuous integration server with targets for each of the client projects and the common DLL project.
This way you'll immediately know when changes in the common DLL breaks any of the client projects. It could reduce the trouble of updating client projects when common DLL's interface changes. This solution might be inadequate if you development team is distributed and very large.
I wouldn't say there is a RIGHT solution though. There are many ways to manage dependency problems.
You could also have a look at Maven. It will help you set up project dependencies. Not sure how you can integrate Maven into Visual Studio though. Maven will allow you to specify which version of a project (in SVN) you want to depend on. Developers will then be able to checkout the correct project version and build their projects. Maven will checkout the correct version of the dependent projects from SVN for them. I haven't work with it myself, but a lot of open source projects in the Java community uses it.
I have quite a large project, actually 2 but they share a lot of projects between each other. The problem being when I compile from NOTHING, that is, no DLLs in my common bin directory, it fails..
This is due to the fact that some projects are not compiling before others that are dependent on them.
I have fixed it manually going through them and it now works.
But I was wondering if there was some sort of plugin or trick to force a READ of the solution and build the dependencies and build order correctly?
Also it's a mystery that some projects had a tick next to some projects in the project dependencies dialog and others not, any idea why?
Why did Visual Studio 2008 decide to say "hey that's a dependency on that but that isn't when it is" :-) ?
If you rightclick on your project you can go to Project Dependencies and check off what projects your current project depends on. Also you can right click and go to Project Build Order to see the order in witch your projects build.
VS will try and infer the build order from the references of each project. If project A contains a reference to B then B will be built before A. Usually this works reasonably well. If your projects have a dependency that's not expressed as a reference then VS will not pick it up. For example if you're using a dependency injection container then you may not want/need explicit project references.
As Bruce points out the solution in this case is to set dependencies and the build order manually.