I have two versions of my application. The first one use references of library LIB_A, the second one use references of library LIB_B. (LIB_A and LIB_B are in fact to versions of the same product, but they differ from each other, even namespaces are different.There can't be installed two versions in the one machine on the same time).
Sourcecodes of my application in both versions are almost the same so I need to have one solution, that can switch which library to use.
How can I do that?
Since you specified VS2010 in your comment, I'm adding this answer separately, so that users of VS2015 can refer to the other answer, which is a lot cleaner.
In VS2010, you can use source code sharing between the two projects. Let's say that you have created AppA, which is the app project that references LibA, and contains all the sources for the app.
You can create an app project, AppB, that references LibB. It also shares all the sources of AppA. This can be done in one of two ways:
Linking All Sources Manually
In AppB, you can create the same folder structure (if any) as AppA. Right click each subfolder and click Add->Existing Item... Navigate to the corresponding folder of AppA and select all the C# files. Now click on the dropdown to the right of the Add button and select "Add as Link". You'll notice that the added sources have a little "shared" arrow in their icons, and that their paths point back to the original.
Linking All Sources Dynamically
If you have lots of files in AppA, or add/remove files regularly, the previous approach can get tiring. There's another way to do this that involves hand-editing AppB.csproj. Open AppB.csproj and create an ItemGroup that imports all the files from AppA. This code assumes that AppA and AppB are subfolders of the solution folder. If not, change the relative paths appropriately.
<ItemGroup>
<Compile Include="..\AppA\\**\*.cs">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
</ItemGroup>
Now when you open the solution, you will see that AppB's contents match that of AppA. The sources are linked, so AppB's conditional build settings (if any) will apply.
You can also exclude files from being included by adding an Exclude attribute to the Compile tag. See the VS documentation for more details.
The only downside of this approach is that you need to hand-edit the csproj file. Also, if you accidentally delete or move linked files, VS will hard-code the list of linked files into the project. The files themselves will still be linked.
It so happens that Visual Studio 2015 (you can download the Release Candidate, which I've found much more powerful and faster than VS2013) has a feature that is designed for this very purpose - Shared Projects. Here's a Channel9 video that describes it.
A shared project contains source files that are compiled directly into projects that reference it. Let's say a shared project Shared has a file foo.cs, and projects AppA and AppB both reference project Shared, then file foo.cs is compiled directly into AppA and AppB - it uses any conditional settings of those projects. So foo.cs could have code that looks like this
#if APPA
// do something
#elif APPB
// do something else
#endif
So to summarize:
Within a single solution, create a Shared Project with all your app sources.
Create two projects AppA and AppB, that represent the two flavors of your app.
AppA references Shared and Lib_A. AppB references Shared and Lib_B.
If needed, add compile variables that control differences in the sources as described above.
Related
I'm in a situation where I'm required to put my development environment (VS2015 and Solution) at a Client's location.
I'm wondering if there may be, perhaps, a better way than to have all the sources there.
My Solution is comprised of multiple Projects, the main part of which constitute a non changing Engine. Is there a way, then, that I can have those Projects (which should never change) as OBJ files (for example) or other files which aren't just flat text files containing all the sources?
While other projects (two or three of them) would remain Source based (cause I'm more at ease showing those sources to the client)?
Compile your sensitive sources into .lib files, and link those into your project. You could also make .DLLs but that would be more effort.
You may have to make multiple copies of your .lib files if you have multiple project configurations (e.g., 32 bit, 64 bit).
Create a new project an add the solutions you want so distibute to it.
Compile all other parts you do not want to give away in source and add the compiled dlls as references (Right click on a project and click the "Browse" button in the Add Reference dialog).
Be sure to set the property "Copy Local" of added references to True.
Create NuGet packages for the project sources you don't want to share or have on site.
Reference those NuGet packages from projects or solutions that you're ok with having the source available.
I have a smallish solution, with about under twenty projects. The solution used to also contain about six source projects written by a third party service provider, ACME. Now, finally, this other party is supplying us only with a handful of DLLs. I used to just included their source, one project per DLL, in the solution, and so I am looking for a neat way to include all these assemblies in the solution, so they can be referenced from the many projects that need them.
My immediately apparent options are:
Create an AcmeAssembly project, add all DLLs as project items set to copy to output.
Create an AcmeAssembly solution folder. Quicker and simpler than a 'binary-only' source project, but solution folders have the very, very large drawback of having no means of grouping the files without a solution file, i.e. outside of VS.
Create a NuGet package that includes all the required binaries. Then at least we also have a partly 'phycical' grouping in the packages folders. My problem here is I have never written a NuGet package, but I am not asking how to here. I am asking about three candidate solutions, and more will be welcome, and if NuGet wins, I get to learn to write a package.
I can't simply use the project's output bin\debug and bin\release folders. To me, these are strictly output folders, and nothing but other dependency assemblies should also be output there. Deleting the bin folder should have absolutely zero effect on a build, so that is certainly no place to store binaries.
The advantages of nuget over the other solutions are:
Support for versioning
Support is built in into Visual Studio and MSBuild
No 'magic folders' that all developers need to have on their machines
Create your Acme library folder (something like: C:\Source\Library\AcmeLibrary). Put all of your Acme dll's in that folder. Then create the Solution Folder in VS and add the existing items to it (don't add the folder, but the items in the C:\Source\Library\AcmeLibrary folder to the solution folder using "Add Existing Item..." menu selection).
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.
I'm using Visual Studio 2010 Pro to build a solution that contains two projects. Project A contains most of my source code, while Project B is intended to run independently, but must use some of the source code contained in Project A.
Under the current configuration, Project A is contained as a reference within Project B. I'd like to be able to build and maintain versions of each project independently, but it appears that when I build the entire solution, ProjectB.exe cannot run without ProjectA.exe in the same local directory. I would think and hope that when the .exe binaries are compiled that all of their dependencies are packaged within each, but that appears not to be the case. In fact, any attempt to run ProjectB.exe while ProjectA.exe is not present results in a System.IO.FileNotFoundException.
Is there a way to build a version ProjectB.exe that runs independently and avoids code duplication?
In cases where you want common code, the best solution is to break out the common classes into a third assembly to serve as a library. (As per Adriano's suggestion.) The other option he hints at is to use the "as link" option when using the "add existing file" to the second project.
If you don't know where it is, use the "Add existing file" option, then in the dialog box to select the file, the "Add" button has a drop-down selection where you can select "As Linked File" (or something to that effect.)
This allows you to compile the same classes into multiple projects. But keep in mind that the namespacing for the linked file cannot be changed for the second project. If the namespace was "ProjectA.Domain", this is how you need to access it in Project B. This was a useful trick for Silverlight projects back before the multi-platform assemblies were introduced.
If you want to get rid or the dependency on A, you will have to extract the common logic into another project (let's call it C), as Adriano suggested in a comment.
If you need even looser bond between the projects, you can reference A (or C) not as a project, but as a built assembly (.dll file) and check Specific Version reference property to True. Additionally, if your project/codebase structure is more complex, check more assembly sharing options here.
Some options:
The common option: Separate the common code into a third class library (DLL) project. And have both ProjectA and ProjectB dependent on it. The downside is that now in order to run the projects you need two files (the main exe and the dll.) This method is how most software is developed: a single executable and a bunch of DLLs.
The correct option: Separate the common code into a third project and modify the project files to create executables that contain both assemblies (similar to statically linked libraries in unmanaged code.) The downside is that Visual Studio does not support this out of the box and you need to modify the project files which are actually MS-Build definition files to do this.
The ugly option: Create shortcuts for the common files in ProjectA in ProjectB. This is the same as copying the common code to the other project, but you're still left with one source file. The downside is that you have to do this for every file and maintain the same structure in both projects. This is an ugly, if viable, option. Choose one of the others.
Our project has a lot of external DLLs, most but not all of which are 3rd party DLLs.
Currently we do not have these DLLs included in our project. They are included in SVN and given a path to our build output directory. So, after building our project the neccessary files are there, because of SVN, but the project itself has no knowledge of them.
My feeling is that we should have a folder under the root of our project named something like Dependancies or ThirdParty with all of the DLLs included there and set their build event to copy to the output directory. They would exist in SVN as well, but in the same structure as the project, not in the build output directory.
The project itself only references one of these DLLs called CommunicationProc.DLL. The CommunicationProc.DLL then references all of the other DLLs. We have numerous DLLs to support different types of radio. So not all DLLs will be used, but any one of them may be used depending on the radio type.
As to whether or not the DLLs should be included in the project we have differing opinions internally, some of the team beleives they should only be in SVN and not part of the project itself.
Of note is that this are not .NET DLLs, most are old C DLLs.
What is the accepted practice? Can someone please provide me with a compelling arguement one way or the other as to whether to include them in the project or just SVN?
Its better to have them in a folder on source control and then copy them over to the debug folder on build event. This way you can manage their versions. If a newer version of some dll comes then you can replace the old one and put some comments with check in. Also if you are working in a team, then instead of copying files from debug folder to each team member, you can let each team member to use the same set of dlls from source control. If you are developing some control and want your customers to use that control then its easier for you to have a set of dependent dlls some where so that you can give those to your customer along with your .Net dlls.
I had the same issue with some un-managed dlls and ended up putting them in a folder so that all the team members have the same version of the dlls. Hope this helps.
I include a project that has no code but contains a folder where all the external assemblies and their dependencies are kepts. For each file set the Build Action to None and Copy to Output as Do Not Copyp. The project then references the binaries from this location. In your other projects, reference this special project. When you build, because the special project is referenced and it references all the needed dependencies, the binaries are copied as needed.
If you do not want a special project, still create the folder in your main project, added the assemblies, set their properties, then reference the assemblies as needed.
This gives you complete control over the versions and output, and more importantly, it is simple.