EventHandlerList missing in PCL project but available on platform library projects (Android/iOS) - xamarin

I have small problem - I'm trying to implement class that needs to contain a lot of events. Due to memory concerns I planned to implement EventHandlerList which is available for me in my Android Library project target also in my iOS Library project target but is not available for me inside PCL Project. Tried to change PCL Target project to most commonly used but none of them contained what i needed.
Type missing for my case :
System.ComponentModel.EventHandlerList
Is there any possibility to write such class once or I'm forced to write it two times because of missing PCL Target.

You will need Inversion Of Control (IoC) to use platform specific features or non-portable methods
Please take a look at this IoC example
Another option if you want to avoid IoC is to use Shared Project in Xamarin

Related

Extracting common code from Xamarin Android project

I've been writing a Xamarin Android app and am now in a position where I have a load of generic business logic (including SQLite.Net stuff). I would like to move this to a separate project, in case I decide to have a go at a Xamarin iOS project. Can this just be a vanilla class library project or is there more to it?
This business logic code contains some strings that will need localizing. I guess the only option will be to store them in a resx resource file in the new project?
For the project itself you can use a PCL, this is in fact my favorite option of sharing code between projects in a Xamarin solution or you can go with Shared Projects which I don't like it very much but many people use it and it works. Here's the link I always use as reference when asked which one to use so you can decide yourself based on the pros and cons of each one.
About the localization you can definitely use a resx resource file but you will need to implement your own localization service to read from the files.

Xamarin portable library - how to share classes

I'm building a project that includes an MVC Web Api hosted in Azure and an iOS app. I'm trying to use Xamarin to build the app. As I understand it, I should use a portable class library in my Xamarin project to allow me to share the code between my Web Api project and the Xamarin app, as well as any future apps on other platforms like android.
So right off the bat I would want to put my models in the portable library. The app and the web api will pass those models back and forth. But the portable library doesn't have the Azure Table Storage library. It doesn't even have some very basic stuff. My models need to reference the Azure Storage Library so I can save instances to storage.
What is the best way to make this code shareable? Obviously I need to duplicate my model classes so they can exist in each location. But should those in the PCL inherit from those in the Web Api project? Vice versa? Should there be an interface that both inherit from (actually the Azure Table Storage library requires the classes to inherit from ITableEntity already...). Just looking for the best way to share these classes between the Web Api project and the PCL used by the Xamarin project.
Using a PCL - Portable Class Library is a great way to get started! There are a few quirks that you may want to understand prior to sharing your code.
The PCL Profile is a limited set of APIs available. Meaning that certain classes/assemblies might not be included. You can typically look up the class/assembly via MSDN and see if it has a PCL icon next to the class name.
If the library you are trying to use has assemblies not inside the current PCL Profile but can be found on the native platforms, you will want to use the IoC/DI pattern.
Hopefully the library you're using supports PCL. Otherwise, you will need a library that does support the PCL Profile. (You can check this by downloading the .nupkg, extracting, and looking at the libs folder). Note: You may want to check the Prerelease NuGet channel for PCL support. Sometimes you can find an open source project and remove/replace certain assemblies/code to make it Portable.
General Guidelines:
Keep your POCO classes simple in the PCL. If you have platform specific quirks you need to add to the models, make a Model layer on that platform that inherits from your simple PCL models. EX: Your Web API has a specific [Attribute] tag or interface that you need to apply to your model. You might already have a Model such as Person which is a simple POCO class in your PCL, and then you can create a PersonApiEntity model which might inherit Person and any platform-specific APIs you need to apply to it.
It seems ITableEntity/TableEntity is not supported in the PCL Profile.
https://msdn.microsoft.com/en-us/library/microsoft.windowsazure.storage.table.itableentity.aspx
Seeing the source at a quick glance(https://github.com/Azure/azure-storage-net/blob/master/Lib/Common/Table/ITableEntity.cs)

Which one to choose Shared Project or PCL for sharing code?

Just wanted to understand there are couple of code sharing strategies exist to achieve code reusable capability in Xamarin.
Which one should i use ?
Shared Project way OR Portable Class Library way ?
if you can explain with scenarios , it would be very helpful for me.
Thanks much.
Here is the Xamarin explanation.
The question is possibly duplicated but you ask specifically for scenarios.
If you ever wrote c cross platform projects, shared projects resemble the old-school way allowing you to use #if __IOS__ statements to run device platform code in your shared/common code files. A separate assembly is created for each target (say iOS or Android). They give advantages and disadvantages of each.
PCL generates one single assembly for the common code. PCL has some limited number .net features as shown here in this table. However, most of the important .net goodies are there as you can see.
Xamarin says that shared code method is easier but PCL is easier to compile a module and share or sell that with others.
When I make projects, I check what external plugins/components/ etc I want to use and make a decision based from. For example, you may want to use sqlite and there are different options for using shared and PCL projects.

Xamarin Shared Library and PCL

What is the exact difference between xamarin shared project and portable class library?
When to use shared library and when to use portable class library?
Is this possible to write native functionality in shared projects like showing alert,accessing camera and use it for both android and iOS?
Can anyone please explain me.
In shared projects each code file will be compiled for each destination (Android, iOS, Windows Phone etc). You are able to include platform specific code by using #if compiler directives.
When you want to access the camera you need to write the access code inside an #if block for all destinated platforms. This can mess up your code but it can be easier to find the different implementations.
Learn more: http://developer.xamarin.com/guides/cross-platform/application_fundamentals/shared_projects/
Protable Class Libraries (PCL) are compiled against a general .NET subset which is compatible to all platforms you want. So you can access System.Net.Http but you cannot access any platform specific code. If you want to access the camera inside the PCL code then you need to access it by a generalized interface via dependency injection. There are some pretty good frameworks helping you to archieve this goal. One of the most famous is MVVMCross (https://github.com/MvvmCross/MvvmCross/wiki). Learn more about PCL: http://developer.xamarin.com/guides/cross-platform/application_fundamentals/building_cross_platform_applications/sharing_code_options/#Portable_Class_Libraries
I personally perefer PCLs because the code is much easier to read without any compiler directives. Using MVVMCross you are able to use plenty of plugins via NuGet. So you don't need to write your own classes for camera access, showing alerts etc.

MvvmCross vNext: Using System.IO.Compression in PCL

I have some Model code that requires some methods from the System.IO.Compression namespace. However it is not present when using a PCL that targets VSMonoTouch and MonoAndroid as well. I see that some stuff is TypeForwarded in the MvvmCross solution, though when creating a similar project I can't seem to find out how to use it.
I created a MonoAndroid library project and added a Forward.cs class with the following content:
using System.Runtime.CompilerServices;
[assembly: TypeForwardedTo(typeof(System.IO.Compression.CompressionMode))]
[assembly: TypeForwardedTo(typeof(System.IO.Compression.DeflateStream))]
[assembly: TypeForwardedTo(typeof(System.IO.Compression.GZipStream))]
I have set the namespace of the project to System.IO.Compression. Trying to add it as a reference to the PCL project I have with my Model code which contains ViewModels, Services and what not it of course says that it can only reference other PCL projects and assemblies.
I especially need GZipStream and I cannot seem to find out how to add it to my project, so the question is how do I do that?
PCL Extension route
How to do this by extending PCL... I'm not entirely sure! One of the PCL guys might be able to assist with that.
Plugin route
The way I'd go about this is by defining the functionality I want in an interface and wrapping the code in a plugin.
For example in Cheesebaron.Plugins.Gzip.dll you could create an interface like:
public interface IGZipStreamFactory
{
Stream Decompress(Stream binaryStream);
}
This interface would then get plugged inside a PCL library that just contained this interface and the pluginmanager class.
Your PCL Core project can then reference this PCL plugin library and your ViewModel can use code like:
Cheesebaron.Plugins.GZip.PluginLoader.Instance.EnsureLoaded();
followed by
var service = this.GetService<IGZipStreamFactory>();
var unzipped = service.Decompress(inputStream);
For each actual platform implementation, you then prepare a platform specific library, you implement the GZip factory interface, and you provide a simple Plugin class implementation.
For example, for Droid you might create Cheesebaron.Plugins.Gzip.Droid.dll:
public class MyDroidGZipStreamFactory : IGZipStreamFactory
{
// the implementation
}
And you'd then add:
public class Plugin
: IMvxPlugin
, IMvxServiceProducer
{
public void Load()
{
this.RegisterServiceInstance<IGZipStreamFactory>(new MyDroidGZipStreamFactory));
}
}
Finally... to pull it all together, for MonoDroid you then reference both the PCL and the platform specific implementation in your UI project - and it should all work!
Note that there is a little convention based magic going on behind the scenes here - the framework loads the Assembly Cheesebaron.Plugins.Gzip.Droid.dll based on the PCL Plugin namespace being Cheesebaron.Plugins.Gzip
(For WP7 and other platforms, there's one additional step - there's a setup method to override which registers the plugin)
Note you can register as many services as you want to inside a single PlugIn, and you can perform extra common initialization/setup code too. This can help to reduce some project maintenance overhead: you can put your CheeseBaron IoC objects inside one single CheeseBaron.Plugins.Utils project if you like and then share just this one plugin across all your apps.
The DownloadCache Plugin provides a small sample of this - it registers all of IMvxHttpFileDownloader, IMvxImageCache and IMvxLocalFileImageLoader.
The downside with doing this is: eventual linked exe size - you're potentially adding unneeded code to each app.
Obviously this plugin approach has a little bit of a learning curve... and it does add a little project maintenance - but the good news is that these plugins can be used over and over again between projects - and can be shared between organisations (at least, that's my hope!)
More on creating plugins at:
MvvmCross vnext: merge plugins with monodroid
http://slodge.blogspot.co.uk/2012/06/mvvm-mvvmcross-monodroid-monotouch-wp7.html
For examples of plugins (not all available on all platforms), see https://github.com/slodge/MvvmCross/tree/vnext/Cirrious/Plugins
Other routes
If you don't want to use Plugins - e.g. if you are ever in a hurry or if you are writing code for a module that you don't want to reuse, then there are alternatives:
You can define an interface like IGZipStreamFactory in your share Core PCL library. You can then provide a platform specific implementation of this interface within each UI project, and can then use normal IoC/DI in the ViewModel/Model/Service layer in order to locate the correct implementation at runtime.
Or...
You can just dump the shared PCL core library and create separate platform-specific DLLs into which you then manually link in platform-specific files (I try never to do this, but others like it)

Resources