Targeting individual platforms with Visual Studio - c#

I am writing an app that would work for both .NET and Mono. However components of it would only be available for one or the other. For example, a modular part of the app use WPF, which is not available in Mono (it would not even build!!!). Another part of the app uses PInvoke on a libpango, which is normally only available on Unix.
Is it possible to target individual platform with Visual Studio with different build parameter for each?
Currently The modular parts are not in their own project file, but I can easily move them to.

#define/#if blocks are one method for doing this. There is also a conditional attribute. You might also want to look into MSBuild targets.
You might also want to think about your class design and whether you can share have shared interfaces that enable more of a provider or "plug-in" model to support different platforms. Microsoft developed a Portable Libraries project type that might help with this.

Conditional compilation can make your code hard to understand and maintain. Personally, I am against it.
My suggestion is that you utilize good design patterns to isolate the platform specific bits,
http://codebetter.com/patricksmacchia/2011/11/07/real-world-feedback-on-a-net-to-mono-migration/
JavaDepend is a Windows Forms project, so its porting experience may help you.
WinForms executable (.exe) -> Platform adapter (.dll) -> Windows (.Windows.dll)
|
--> Other platforms (.Unix.dll)
In this way, you can always compile the whole solution together, package them together. At runtime, the adapter can load correct platform assembly/assemblies after platform detection.
For you case maybe you can use WPF for Windows, then you have to isolate WPF bits from business logic code, and then write UI again for other platforms (GTK# for Linux, MonoMac for OS X). This approach can be visualized as
WinForms/WPF executable (.exe) -> Platform independent biz-logic code (.dll)
^ ^
MonoMac executable ---| |
|
GTK\# executable ------|
In this way, you need to package differently for each platforms, but the core assembly/assemblies can be the same.

Related

Packaging platform-native (C++) code with C# bindings using nuget

So, I've been searching around about the ideal way to build a cross-platform .NET (C#) application that also relies on some native code bits.
Since I couldn't find a de-facto way to build these things together, I turned by attention into the following workflow:
Build native code (c++ -> native "dll"(.dll/.dylib/.so/etc);
(Generate bindings, w/ SWIG or something, or have a project with them);
Package said project into NuGet;
Consume from the cross-platform application.
Now, Microsoft itself has some suggestions about this. But this - and all other - guides I've found so far have the same quirk: include pre-compiled binaries into the folder structure. This bothers me because:
It makes version control hard, because you have hard-copied build artifacts;
It completely breaks CI/CD because you can't just have a matrix of CI machines each one doing their build/package/upload.
It breaks the development workflow because you need to constantly be building + copying files over.
But, looking around in the NuGet Gallery, there seem to be packages more in the direction that I thought of, for example in the SkiaSharp, and Avalonia packages.
My idea is that there should be a series of for-one-platform-only packages (plus eventually an "aggregator" package) that could be transparently consumed.
Is this a possible workflow? If yes, how? If not, what is the currently agreed upon workflow, and how does it tackle the issues I mentioned?
Just to make it clear, I want to develop the native library and consume it in the cross-platform .NET (5/6) application in a simultaneous fashion, it's not that I'm binding a mature library, with periodic releases, that would make the mentioned workflow easy.
Thank you.

Is there any way to share code between UWP apps and WPF apps?

To be clear, I follow the MVVM pattern, and I want to structure my project such that I can share my model code between a UWP app and a standard WPF app. The code I want to share has no UI. I don't relish the thought of finding new tools to replace the ones that I've been using for years that take care of certain tasks like logging, connecting to a document oriented database, etc.
I attempted to start writing a UWP wrapper around some code I already have and reference the model project directly. Visual Studio refused to let that happen, showing me an error message that says "Unable to add a reference to project 'ACK.Model'". The same thing happened when I attempted to put the model in a Universal Library and reference it from a WPF app. I'm not trying to share WPF code. Just the model layer that has no reference to UI libraries.
This is a scary proposition, because it means that if I want to do anything substantial I have to choose to either jump 100% to UWP or stay 100% WPF. NewtonSoft.JSON might have a universal distribution (ASP.NET MVC), but what about ElasticSearch.NET, and other tools needed to make important apps?
I found where the "Portable Class Library" project type was hiding. PCLs will allow me to share my code across WPF and Universal apps as that was one of the options. This solves the simple case of the Model part of my code, but I (still) can't use some of the libraries I want. There are still a large number of libraries that I need that do not have PCL available.
About a year later, with the advent of Visual Studio 2017 there is a more complete solution. If you target your libraries to .Net Standard then the library is compatible with both .Net Core apps and the monolithic .Net targeted app. The support for standard .Net libraries and APIs is fairly complete, as is the support for modern C# language features.
The general advice now is this:
Target .Net Standard for all libraries
Target the appropriate platform for your actual application. (UWP or WPF).
NOTE: if your library has to interact with C libraries or applications, you have to take extra care to make sure you load the correct version.
It appears that there is a solution, but it has to be adopted by the whole tool chain you want to use. When Microsoft introduced Windows Store apps in Windows 8, they also introduced a Portable Class Library (PCL). The purpose of the PCL is to share code between different parts of your application.
When you create a PCL in Visual Studio 2015, you can specify the types of APIs you want it to be accessible from:
Universal Apps
Mono
.Net Core 5
.Net 4.6
This of course, limits the APIs available to you but most of the ones you want to use are OK as long as it's not UI related. There are other limitations as well:
Your project can only be edited in Visual Studio 2015 or greater
You don't have access to special directories from the Environment variable (i.e. user Documents directory, etc.)
You can't link to a library designed for only one of your target platforms (i.e. libgit2sharp, etc.)
There's no way to browse the API for this subset--MSDN needs to get on the stick. MSDN has updated much of the API documentation, but it's still difficult to figure out what applies to your PCL
However, you can link any library designed for a single target platform to your PCL. It's not ideal, but it's better than nothing.
The ASP.NET MVC stack has been ported to using PCLs, so you can use NewtonSoft.JSON directly as well as any other of those libraries used by that application. However, there are several libraries that have not been ported.
This arrangement forces you to think about how you want to integrate better. The .Net Core 5 seems to be stable, but support is in it's infancy. The current generation of Universal Apps as of VS 2015 update 1 uses .Net Core 5 directly.
There are several features from Nuget that are not currently supported even though work is under way:
MS Build extensions (major changes to MSBuild and the project.json structure)
Install/uninstall scripts (related to the removal of the concept of install)
Content (related to install/uninstall, but work is in progress on this)
Content transforms (related to lack of install/uninstall)
I wish I had a more complete answer. But this is as far as I got once I discovered the PCL and how it evolved for the current infrastructure.
I'm in the process of creating a game creation toolkit that incorporates version control right off the bat. I want to be able to deploy a game as a Windows 10 app, or as a standard WPF app, but due to the libraries I'm using to integrate version control I need to create the editor as a standard WPF app. I had to be a bit creative in building the shared code and importing the correct libraries.
First, my project hierarchy:
Project.Model (Portable Class Library)
Project.Model.Versioning (standard C# library)
Mvvm.Toolkit (Portable Class Library)
Editor (Standard WPF application)
I want the core PCL to be able to load a project and deserialize the JSON encoded objects. The PCL did have access to System.IO, but surprisingly it is not the same as the one defined in the standard C# library. Here's how I had to fix things:
After adding the package reference to NewtonSoft.JSON, I had to change the target framework in the packages.config file:
<package id="Newtonsoft.Json" version="8.0.2" targetFramework="portable-net452+win81" />
All projects dependent on my Project.Model class had to install the `system.io.filesystem' package from nuget so that the System.IO.FileInfo etc. objects were the same.
While this is definitely not a panacea, it's also not a dead end. I'm sure there are more gotchas, but this will at least help with some of the problems.
a .NET Standard library could be used to share a Model-View-ViewModel architecture between a WPF project and a UWP project.
https://www.syncfusion.com/ebooks/xamarin-forms-succinctly/sharing-code-among-platforms
https://devblogs.microsoft.com/dotnet/announcing-uwp-support-for-net-standard-2-0/

DLL project should be of which type for cross platform use

We have one application for both C# .NET and Apple iPad. This application will perform similar functionalities. For this we have one protocol layer which we are thinking to keep as common code. For this we are thinking of creating a C++ dll for the protocol module so that it can be used across both C# and iPad. For creating a C++ dll, I have a basic question:
While creating a dll project, which option should we select? We can create a dll for MFC, Win32, ATL etc. What would be the best option for my requirement?
You should not use MFC as these are the Microsoft Foundation Classes not available on iOS anyway. Probably Win32 would be your best guess - but make sure not to include any non-standard Windows header files if you want to use the DLL in non-Windows environments.
I would recommend to frequently compile your file in both environments. You might also want to take a look at multi-platform libraries like boost if you need advanced functionality.
I recommend looking at Mono for building C# apps on both Windows and iOS.
If you want to target the iPad, you need to build for iOS, not Mac OS.
You cannot build dynamic link libraries for iOS, only static libraries. Note, there are equivalents to DLLs on iOS, but only Apple can build them (or you can build them yourself if your iPad is jailbroken, but this will disqualify your app from the AppStore).
iOS is not related to Windows in any way, so Win32 libraries will not run on iOS. Your generic 'protocol module' (if you mean low-level code that can interface to other devices over TCP/IP or similar) will need to have significant differences depending on which platform it is running upon.

I want to use a regular class library on XBox360!

why can't I use regular class libraries in XBox360 games?
I have application logic which I want to keep independent from XNA and use in both WPF and XNA applications.
Does anyone know good practice to share code between XBox/Phone7 applications and "regular" windows applications?
Have a look at Portable Class Libraries: http://msdn.microsoft.com/en-us/library/gg597391.aspx
Using the Portable Class Library
project, you can build portable
assemblies that work without
modification on the .NET Framework,
Silverlight, Windows Phone 7, or XNA
(Xbox) platforms. Without the Portable
Class Library project, you must target
a single platform and then manually
rework the class library for other
platforms. The Portable Class Library
project supports a subset of
assemblies from these platforms, and
provides a Visual Studio template that
makes it possible to build assemblies
that run without modification on these
platforms.
Edit: Check out JoDG's answer for a nicer solution.
You could try linked files...
In your Xbox project, right-click -> Add Existing File, then after selecting the file(s), click the little drop-down arrow on the "Add" button and click "Add As Link", as shown here:
This might not work if you need to share more than just files, but it's an easy way to share code.
JoDG's answer is probably the most practically useful. But just to provide additional information:
why can't I use regular class libraries in XBox360 games?
Because the different XNA platforms target different versions of the .NET framework.
XNA Game Studio itself provides a mechanism (documented here and more info here) for automatically mirroring the source files of a project between two projects. This mechanism can be used for creating copies of your library projects for each platform, as well as for your game projects.
For XNA-related work, this is the preferred method for creating cross-platform libraries. When you have to also make your library work on WPF you have to take additional steps:
On Windows, an XNA game is just like any other .NET application, and a XNA library for Windows is just like any other .NET library. Except for the fact that they reference XNA assemblies. So your WPF application can reference a Windows version of your XNA library. But if you want your application to work on systems without XNA installed, you need to remove the XNA assembly references from the Windows project for that XNA library.
XNA Game Studio will still mirror changes between the Windows library and the Xbox 360 library for you.

Is it possible to create a Mono bundle that includes WPF libraries?

I know WPF libraries arenĀ“t implemented by mono class library, however(as far as I know) the mono 2.6 runtime is fully compatible with the .NET 2.0/3.5 runtime, so if the WPF libraries only make PInvoke calls to windows api it is theoretically possible to run a wpf application on windows using the mono runtime.
The reason for wanting that is deploying a wpf application as a standalone executable for windows. Has anyone tried something like that before? If so, what were the results?
In short... No
At this point, the Mono project does not have plans to implement Windows Presentation Foundation APIs as part of the project
Mono will provide Moonlight support which, from what I understand, would also use a subset of XAML to create its UI (the same as Silverlight does) but there are legal complications involved. Such as, it's limited to non-microsoft and non-mac platforms.
If you want to find a list of open-source cross-platform alternatives to WPF/XAML I'm working to compile a list of viable alternatives.
Well I did give it a try with little success. I first checked with corflags if required dll-s are implemented in mixed mode (PresentationFramework, PresenationCore, WindowsBase, System.Xaml). They are all pure CIL implementations so that should work fine with mono. Next I installed mentioned DLLs into mono's GAC and tried running a very simple WPF application. This is what I got:
Assertion at mini-codegen.c:1186, condition `reginfo [sreg].born_in
0' not met
This application has requested the Runtime to terminate it in an
unusual way. Please contact the application's support team for more
information.
So although in theory this should all work, WPF is probably way to complex to run out of the box on mono, it would be cool if there was a pure CIL implementation of WPF that was compatabile with both mono and .NET Framework.
As much as I know, Mono does not support WPF.
Also, WPF uses graphics modules and interacts directly with the GPU. So I can't see how u can use WPF with no hidden pinvokes.
Sounds like you need to read about WPF architecture to better understand it.
http://msdn.microsoft.com/en-us/library/ms750441.aspx
Many pieces are missing in Mono and solely available in .NET. Therefore, your "theory" is not correct, and you cannot run WPF applications on Mono, even on Windows.
At MIX 2010 Miguel de Icaza said in his session that Mono isn't going to support WPF. Anything tangentially related to WPF-like support is only to provide what is needed for Moonlight.
Not fully, but..
You can use Moonlight 4 ( silverlight 4 ) in a desktop mode:-
https://github.com/inorton/MoonBase - MVVM helpers
https://github.com/inorton/XamlPreviewer - XamlPad clone

Categories