Question

We have a TeamProject in TFS dedicated to generic code, like general extension methods, utility classes, things that can be shared with every team in our company. It works like an extension to the .Net framework itself in a way.

There are currently a bunch of projects separated by area, so that when a team wants part of the functionality they don't have to drag a bunch of dependencies with them every time. The naming convention for these projects follows the format [OurCompany].Framework.[Equivalent .Net Namespace].

Here are a few examples of the dlls we have in the solution:

  • Mobiltec.Framework.dll
  • Mobiltec.Framework.Web.dll
  • Mobiltec.Framework.Data.dll
  • ...

The problem arises when we try to make the same extensions for different platforms. For instance, there is a Mobiltec.Framework.dll that targets Silverlight, as well as one for the WindowsMobile platform. When the solution is built on the build server, every output goes to the same folder, and only the last built dll with the same name remain (the previously built ones are overwritten). This obviously leads to errors occurring for every next project that depend on the overwritten files.

I thought that not specifying the platform on the dll names is a good practice and seems to be the standard for third party libraries and even the .Net framework dlls. Nuget packages also seem to encourage that (log4net comes to mind), where different versions are separated by folders that indicate in which platform/.net version they work, while the dll names themselves are the same.

Should I just create a different solution for each platform and/or each .Net version of this Framework? We currently have two solutions because Visual Studio 2012 does not support smart device projects. There is a Framework.Legacy.sln file, which contains all projects that target the Windows Mobile SDKs, and another one, containing every other project (desktop, Silverlight, etc).

Ideally I would really like to share as many projects as possible on the same solution, because refactoring tasks are much easier that way (some functionality is shared between platforms by linked .cs files).

As I just created a build for this project on TFS (thus just realizing the problem), I separated the Silverlight version of our framework in a different solution and set the 'Solution Specific Build Outputs' option to 'true' on the build definition. We now have 3 solutions (one for WindowsMobile, another for 'normal .Net4' and yet another one for Silverlight 5). At the moment, everything seems to be working as intended, but I feel we are losing that refactoring potential and wondered if there was a better way of resolving this, considering we could add yet another version (for windows RT for instance) in the near future.

What I'd like to know is how should we manage this correctly so that it works with the TFS build system while being easy to maintain together? I'm sure there are others who had to deal with the same problem. How did you handle it?

Was it helpful?

Solution

You have a unique situation in that you want to target many mainstream products but also a legacy product. I see you have two main options.

Portable Class Library (PCL)

Ideally you would want to create a Portable Class Library (PCL). A PCL allows you to target many different platforms with one project. So in your example you would only need one Mobiltec.Framework project and it could be used across multiple platforms. This is still an option for you for the majority of the platforms that you want to support. PCLs are great provided they support what you need. PCLs do not allow for everything but you can get around those limitations with other PCLs, building your own representation of an object, or through dependency injection.

Multiple projects targeting different platforms

With this option you would add one csproj to your solution for each platform that you want to support (You can avoid the problem with build location of assemblies by editing the project properties. On the build tab you can specify the location of the built assembly. Set this to be platform specific). In your example you would have a Mobiltec.Framework that targets Silverlight, one that targets .Net3.5, one that targets Windows Phone, etc. Name each project file something different (eg: Mobiltec.Framework, Mobiltec.Framework.Silverlight, etc.) but keep the assembly name the same (application tab of the project properties).

Each project would make use of the same files by adding them as links. This allows you to make a change in one file but have it effect every project. These projects give you full support of the platform you are targeting but not everything is the same across platforms. You'll find yourself having to #if statements within your code files

public void Foo()
{
#if SILVERLIGHT
        // do something
#else
        // do something else
#endif
}

Both approaches have great benefits and great drawbacks. Ideally you would be able to have a PCL library for all of the newer platforms and one project that targets Windows Mobile. If you cannot achieve this (your newer projects require stuff that is not available) then the second approach is still a great approach. No need for code duplication in either case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top