Cross Platform code resuse with Monotouch - but what about app.config? - c#

System.Configuration is not supported on Monotouch; that actually means you cannot use app.config file types in your project. However, if you have an existing application that is using this .NET feature big time, what to do?
Any suggestions how to deal with it? Ideal situation is that app.config can be kept as it is and that Monotouch can read the settings as defined. In the end, that would mean a kind of implementation of System.Configuration.
Suggestions? Code? Would be more than welcome!

MonoTouch's main difference from the standard .NET is to drop support for System.Configuration, in the same way that Silverlight did.
The reason is that this is a pretty heavy framework and it is not an opt-in feature. If we were to support app.config, we would have to bring System.Configuration even for applications that did not care about, bloating the result.
The solution is to remove the dependency on app.config from your software, in the same way that you would if you used WinRT, .NET on Xbox or Silverlight.

First of all you should realize that MonoTouch is not meant to make apps portable, just to enable developers to use C# for iOS apps.
The obvious thing you can do is to wrap this part into your own configuration management code and reimplement the missing part on the iOS side.
BTW the guys at Xamarin are working to create cross-platform APIs for iOS, WP and Android but I doubt these include configuration. They are meant to support device APIs like camera, compass, etc. and I am not really sure how far they have progressed.

We ported the OpenNETCF.Configuration code from the SDF (and by "ported" I mean simply created a MonoDroid and MonoTouch project file and imported the code files) and it works fine. Of course it's a subset of the full Configuration namespace, but it provided pretty much everything we were using from the app.config files.
The code comes with the Standard and above editions, though if you're cheap I'm fairly sure the code changed very little from the 1.x code base which is free and at the bottom of the above linked page.

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/

The type or namespace name 'IPAddress' could not be found

I'm writing a Xamarin.Forms application and have added a PCL project into my main solution in Visual Studio 2013. I'm having problems with using several standard .net classes. Here's a list:
System.Net.IPAddress
System.Net.IPEndPoint
System.Net.WebClient
System.Net.Sockets.UdpClient
System.Timers.Timer
System.Timers.ElapsedEventArgs
System.Net.NetworkInformation.UnicastIPAddressInformation
My question is: How do I figure out which of the above are compatable with a Xamarin.Forms app, and how do I get them to work in my project/solution?
I've contacted Xamarin support, but get vague help and not specifics...
Does anybody have a good strategy for figuring out what classes are supported and what .dlls are needed in order to use them with a Xamarin.Forms project?
Thanks a bunch for your help.
PS: I've been given the following sites for reference, but they don't seem to have any concise information:
What is supported
NuGet package info
It sounds like you don't understand what Portable Class Libraries actually are. When you create a PCL, the subset of the .Net Framework classes that are available for you to use depends on what profile you choose. A profile are the platforms your PCL can support. In Xamarin, the default profile is Profile 78. Profile 78 supports .NET 4.5, WP8, Win8, WP Silverlight 8, Win Store 8, Xamarin.Android, Xamarin.iOS. So the classes that are available to you are the classes that are platform independent, that run on ALL platforms in profile 78.
Example: Take a look at the implementation of System.Net.IPAddress. The implementation makes use of Sockets. Upon further inspection of this implementation, you can see that that System.Net.Sockets is nothing more than a .NET wrapper around the WinSock API. The WinSock API is a Windows only DLL that is specific to the Windows operating family (ws2_32.dll). So, you can now see that System.Net.IPAddress are high level abstractions of Windows Socks (built for the Windows Platform). Since the ws2_32.dll does not exist in Android, nor iOS, etc, this API won't be available to you because Profile 78 specifies that we need to support other non-windows platforms.
Another example is System.Drawing.Bitmap. That's just a .NET wrapper around GDI+, which is based on the Win32 API. Of course Win32 is not available on non-windows platforms (even Windows Phone), which is why you won't see it in a PCL.
Now with that being said, you may think that PCLs are restrictive, but you can create a good PCL library if you think about them the right way. You can also use patterns like Dependency Injection and Bait and Switch.
So in short, don't count on Microsoft "adding support for all the base class libraries" because that's not what PCLs are.
You can still use System.Net.IpAddress in your Xamarin.Forms PCL by using DependancyService. Make an interface in PCL and declare a method "GetIpAddress" in it. Then , in android /iOS project, you can implement that interface in platform specific project and easily access System.Net.IpAddress. After that, Call DependancyService from PCL project to get the result which is IPAddress of your desire.
Cheers !!!
After some additional e-mail from Xamarin Support, and comments on my additional posting, it appears that MS is quite behind in supporting all of their classes via PCL. Some are supported, but not all by a long shot.
Anyway, in order to use my existing code, I would need to put the source .cs files that I would otherwise be using to create my new PCL project directly in the .iOS project and in the .droid project and recompile that way.
This basically defeats the advantage of using a PCL, but does provide an alternative that allows me to use most of my code unchanged. It would just be nicer if all the xamarin libraries were available as PCLs.. Oh well, eventually MS will catch up and get all of their PCLs up to date so that we can use our custom PCLs more often, instead of having to duplicate code all over the place. (Maintenance Nightmare)...
Anyway, thanks to all for the help.
(Working on the bleeding edge of technology is sometimes painful... But that's why we make the big bucks !!!)

How to use TypeForwardedTo in Portable Class Libraries?

I'm trying to build a Portable Class Library which uses implementations from the platform when available. For example, Lazy<T> is available on .NET 4.5, Windows Store Apps, Windows Phone 8, BUT it's not available on Windows Phone 7, Silverlight 4. When my PCL is loaded on one of the platforms that has a Lazy<T> implementation, I want to use the platform's implementation. When it's not available on the platform, I want to use my own implementation. It seems to be possible because the Microsoft BCL is doing it, but I haven't figured out how to implement it.
I've read that by using the TypeForwardedToAttribute, you can redirect the PCL to use the implementation from the platform. I'm not quite sure how to configure my Visual Studio Projects to achieve this result. If CoreLib is my library, and ShimLib contains my implementation of Lazy<T>. Where do I add the TypeForwardedToAttribute? The attribute requires an actual Type reference typeof(System.Lazy<>), which doesn't work when Windows Phone 7 is targeted in the PCL. If I remove Windows Phone 7, then I can't add a reference from CoreLib to ShimLib because ShimLib doesn't support all the platforms that CoreLib does. How do I handle this?
Yes, I know Lazy<T> is super easy to implement, but it's just an example, and my actual situation applies to many more classes that are less trivial to implement.
The way Microsoft.Bcl does this by shipping two assemblies with the same identity; one with the type itself, and one with the type forward. You reference the one with the type when targeting platforms that don't support Lazy (include portable library combinations that include one of these platforms). And reference the one with the type-forward when targeting platforms with Lazy, this enables to consume libraries built against the older platforms.
Make note, Microsoft.Bcl has a little advantage that you don't have. We ship an assembly that has the same identity as one that is already in later versions, which means that when a Windows Phone 7 app runs on Windows Phone 8, they get the version that's built in, not the one in the shim library. You are unable to mimic that, but that's probably something you can live with in your situation.
The principle idea of type forwarding is very well explained in this question and this article and I'm not repeating the details here. In summary, however, the idea is to be able to reuse a library A without recompiling, even though it references a library B that is being replaced by library C. To that end, library B has to be modified such that it forwards the reference to library C, which is exactly what the TypeForwardedTo attribute does.
How does this help you? Well, you could create your ShimLib such that it is referenced by all your projects, but uses conditional compilation and type forwarding to link it to the framework libraries if they exist. Fortunately, someone already did that for you :)
Edit in response to Matt's comment: You're right, I overlooked that Theraot doesn't fall back to the original implementation. And I guess that will be very hard to achieve without recompiling. The best you can do is probably to follow this strategy, i.e. to have different build configurations for the different framework versions. That way, you can conditionally compile the TypeForwardedToAttribute. At least, this saves you from having to duplicate code. If you really don't want to distribute different versions of your code, you might implement a bootstraper that determines the framework version and loads the version of your assembly that has been compiled using the build configuration for this version

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