37

Share more code on iOS, Android and Windows with Portable Class Libraries

Embed Size (px)

Citation preview

SharemorecodeoniOS,Android andWindowswithPortable ClassLibrariesDanArdelean - MahizMicrosoftMVPWindowsPlatformDevelopmentXamarinCertified MobileDeveloperTwitter:@danardeleanEmail:[email protected]

iOS WindowsAndroid

Objective-CXcode

C#VisualStudio

JavaAndroidStudio

Nosharedcode•Manylanguages&developmentenvironments•Multipleteams

SiloApproach

iOS WindowsAndroid

C#VisualStudioXamarinStudio

C#VisualStudio

C#VisualStudioXamarinStudio

C#codebase•100%nativeAPIaccess•Highperformance

Xamarin’s Approach

Xamarin’s Approach

SharedC#codebase•100%nativeAPIaccess•Highperformance

iOSC#UI WindowsC#UIAndroidC#UI

SharedC#Mobile

Xamarin+Xamarin.Forms

TraditionalXamarinApproach WithXamarin.Forms:Morecode-sharing,allnative

iOSC#UI WindowsC#UIAndroidC#UI

SharedC#Backend

SharedUICode

SharedC#Backend

CodeSharingStatsMac

iOS

Android

WindowsPhone

iCircuit TouchDraw

86%

14%

72%

28%

70%30%

61%39%

88%

12%

76%

24%

90%

10%

DataAccessLayer(Database)

• SQLiteincludediniOS+Androidforlocaldatastorage

• canbeaddedtoWindows

• Canalsostoreinthecloud– AzureMobileServices,Amazon,Dropbox,etc.

WebServices

• UseHttpClient forREST services,canthenprocesswith

• System.Xml /System.Json• LINQtoXML• Newtonsoft JSON.net component

• UseWCFor.asmx forSOAP

NuGet

• NuGet isapackagemanagerfor.NETthatallowsyoutolocate,install,updateandremovesharedcomponentsfromyourprojectsrightinyourIDE(eitherVisualStudioorXamarinStudio)

www.nuget.org

XamarinComponent Store

• CanalsogetreusablecomponentsfromtheXamarinComponentStorewhichisaccessiblethroughtheComponentsfolderineachproject

PluginsforXamarin

CommonAPI

https://github.com/jamesmontemagno/Xamarin.Plugins

WherecanIusesharedcode?

• Anytimeyouarewritingcodewhichdoesnotdependonaspecificplatformfeature,itispotentiallysharable,particularlyifit:

• Talkstoawebservice• Parsesadataformat• Workswithadatabase• Performsprocessing/businesslogic§• …

• Createsharedclasses+methodsandthenusethemfromyourplatform-specificcodetomaximizetheshareablesurfacearea

SharableCode

• Sharable code is split between reusable components and platform-independent code

40%

60%

Your Code

Components

PlatformSpecificCode

•Whatifwedidn’thavetowritethiscode?

•Whatifwecouldaccessitfromsharedcode?

UI+APIs UI+APIsUI+APIs

BatteryGPSLightsNotificationsSettingsTextToSpeech

BatteryGPSLightsNotificationsSettingsTextToSpeech

BatteryGPSLightsNotificationsSettingsTextToSpeech

TextToSpeech

Speak(“HelloWorld”);

AVSpeechSynthesizer SpeechSynthesizer

SharedCode

SharingCodeStrategies

Shared Project Portable ClassLibrary

SharedProject

AnyNote.Droid.csprojNoteFragment.cs

FreehandFragment.cs

NoteViewController.cs

FreehandViewController.cs

AnyNote.UWP.csproj AnyNote.iOS.csproj

NoteView.xaml.cs

DrawInkView.xaml.cs

PortableClassLibrary

• PortableClassLibrariesareassembliesthatcanbeusedbydifferentflavorsof.NETwithoutrecompiling

PCLStrategies

• StandardPCL

• AdvancedPCL– BaitandSwitchstrategy

Standard- PlatformAbstractions

• Complexrequirementscanbedescribedwithabstractionsthatareimplementedbytheplatformspecificproject

PCLINoteDataLoader

NoteManager

NoteItem

ApplicationUI Layer

NoteDataLoader

ApplicationUI Layer

NoteDataLoader

ApplicationUI Layer

NoteDataLoader

Just need a way for thePCL to know about theimplementation..

Providingconcretedependencies

• CansupplyconcreteimplementationtoPCLviaconstructor,methodorpropertysetter;thistechniqueisoftencalledDependencyInjection

var manager = new NoteManager(new NoteDataLoader());OR

var manager = new NoteManager ();manager.Initialize(new NoteDataLoader ());

ORvar manager = new NoteManager (); manager.Loader = new NoteDataLoader ();

PlatformSpecificCodeStrategies

• CanrestrictyourAPIusagetothelowestcommondenominator,oruseanabstractionsuchasaninterfaceoraneventandimplementthatabstractionintheplatform-specificproject(s)

• NeedsomewaytogettotheabstractioninyourPCLcode

Callbacks Factories

Dependency Injection

Event-BaseExtensibility

• PCLscanuseeventsontypestorequestextensibilityfromtheconsumer,particularlyeffectiveifplatform-specificrequirementsaresmall

public class NoteManager{

public event bool ShowAlert(string title,string message);

void OnDeleteNote(NoteItem note) {if (ShowAlert("Warning!", "...")) {...

}}

}PCL

var notes = new NoteManager();

notes.ShowAlert += (title, message) => {new UIAlertView(title, message,

null, "OK").Show();...

};NoteManager.iOS

FactoryPattern

• Dependenciescanbelocatedthroughfactorieswhichareresponsibleforcreatingtheabstractions

Client Factory Serviceuses creates

DefiningtheFactory

publ ic abstract class AlertService{

publ ic s t a t i c Func<AlertService> Create { get; set; }

publ ic abstract string

bool Show(string title, message,

string yesButton,string noButton);

}

DelegateissetbyplatformwhichreturnsimplementationofthedefinedAlertService

SettingupaFactory

• Eachplatformwouldimplementtheabstractionandthensetthefactorypropertytoadelegatethatreturnstheimplementation

class AlertServiceiOS : AlertService{

publ ic bool Show(string t i t l e , s t r ing message,s t r ing yesButton, s t r ing noButton) { . . . }

}

publ ic override bool FinishedLaunching(...) {. . .AlertService.Create = ( ) => new AlertServiceiOS()

}

UsingaFactory

• Thenanycodeintheprojectthatneededthatfeaturewouldgototheknownfactorytocreatetheobjecttobeused

OnReceivedError(string errorMessage)public void{

var alertService a ler tServ ice. Show

= AlertServ i ce.Cre a te( ) ; ( "E r ro r " ,

{ errorMessage} " , "OK", n u l l ) ;$"Got e r ro r :. . .

}

Nowtheclientdoesn'tneedtoknoworcareabouttheimplementation– itgoestothefactorytogetoneandjustusesitfromanywhereinthe app

ServiceLocator

• ServiceLocatorpatternusesacontainerthatmapsabstractions(interfaces)toconcrete,registeredtypes– clientthenuseslocatortofinddependencies

Client Locator

Service A

Service B

uses

locates

locates

ServiceLocatorExampleDefinition

publ ic sealed class ServiceLocator{

publ ic s t a t i c ServiceLocator Instance { get ; se t ; }

void Add(Type contractType, void Add(Type contractType,

object value); Type serviceType) ;

contractType);

public publicpublic public

object Resolve(Type T Resolve<T>();

Uses Singletonpattern toprovide globalaccessibility

}

Providecapabilitytoregisterandlocate types

RegisterDependencies

appl icat ion)

publ ic p a r t i a l class AppDelegate{

. . .publ ic override void FinishedLaunching(UIApplication{

. . .ServiceLocator.Instance.Add<IAlertService,MyAlertService>();

}}

Platform-specificcoderegistersimplementationforthe abstraction

UsetheServiceLocator

public void DialNumber(string number){

var a l e r t = ServiceLocator.Instance.Resolve<IAlertService>();i f ( !a ler t .Show("Dia l Number",

"Are you sure you want to d i a l " + number,"Yes", "No")) { . . . }

}

Clientthenrequeststheabstractionandlocatorreturnstheregistered implementation

ServiceLocatorImplementations

• Easytorollyourown,buttherearemanyusableimplementationsoutthereifyouarealreadyusing3rdpartylibraries

• CommonServiceLocator[commonservicelocator.codeplex.com]• MostMvvm/PatternlibrarieshaveaServiceLocator• Xamarin.Forms DependencyService

DependencyInjection

• Anotheroptionistohavetheplatform-specificcode"inject"thedependencybypassingitasaparameterorsettingaproperty

publ ic class DataAccessLayer{

publ ic DataAccessLayer (IDbResposito r yIAler tService

db, a le r t s ) { . . . }

ILogger Logger { get; set; }publ ic. . .

}

Servicesthisclassdependsonmust besupplied("injected")through constructorparameters,propertiesormethod parameters

UsingDependencyInjection

• Canthenconnecttheclientandrequireddependenciestogethermanuallyinourcode

CreateDataLayer()publ ic DataAccessLayer{

var dataAccessLayer = new DataAccessLayer(new Sql i teReposi tory( ) ,new WinRTAlertService());

/ // /

IDbRepositoryIAler tService

dataAccessLayer.Logger = new AzureLogger(); / / ILogger

return dataAccessLayer}

AdvancedPCL– BaitandSwitch

• DEMO

Domande?

Materialesuhttp://www.communitydays.it/