How to Share Code Across Xamarin Pojects

for  private training for 3 or more people at your site or online.

Good programmers are lazy. They never write the same code twice and they steal from others as much as possible. Or, to say it another way, they leverage good design principles to maximize code reuse and facilitate the integration of 3rd party components.

A cross-platform development framework like Xamarin is all about code reuse: “write once, run everywhere all the places you care about”. In this tutorial, I’ll walk you through setting up a new Xamarin project with the configuration I recommend for most applications.

For this tutorial, I’m be using Visual Studio 2017 with the Xamarin tools installed. The Community [free] Edition of Visual Studio has everything you need: https://www.visualstudio.com/vs/mobile-app-development/#downloadvs

New Project

When you create a new cross-platform project in Visual Studio, you are immediately asked to make two important decisions…

New Project

  1. Will you be building a separate native user interface for each platform or will you be using the Xamarin.Forms cross-platform UI framework?
  2. What will be your “code sharing strategy”? The options you are given are “Shared Project” or “Portable Class Library (PCL)”.

A good discussion about this decision of Xamarin.Forms vs. native UIs is available on the Xamarin forms here: https://forums.xamarin.com/discussion/53829/difference-between-xamarin-forms-and-native-apps-in-mobleapps-tab.

The answer to the first question will have a dramatic effect on how your application is structured; you should try to get that one right. So, what is the right answer? Unfortunately, there isn’t a single choice that’s always the right one. For one application, a single UI built with Xamarin.Forms can work very well and save you a lot of development time. For another application, building a custom native UI for each platform might be the right answer.

For this tutorial, it’s the answer to the second question that we’re more interested in. If you click the question mark icon next to “Code Sharing Strategy” in the new project dialog, you will be taken to a page (https://developer.xamarin.com/guides/cross-platform/application_fundamentals/code-sharing/) that provides a very good overview of the options. I highly recommend that you review that information before continuing (I’ll wait).

Solution Structure

Solution Structure

Now that we have some information about the options, let’s make some choices. In the new project dialog, we’ll choose Native as our UI technology and select “Shared Project” as our code sharing strategy (we’re not actually going to use either code sharing option but we must pick something here). This will give us a solution that looks like this in Solution Explorer (you may also have a UWP project for Windows-based devices):

Instead of using a shared project for our common code, we would like to build a library that is as reusable as possible. For example, we would like the option to add our shared library to our ASP.NET Core-based web version of our application.

Portable Class Libraries (PCLs)

Portable class libraries (PCLs) were developed as a way for developers to write libraries that could be used across different implementations of .NET (full framework, Mono, Silverlight, etc.). PCLs accomplished this by defining a set of profiles – each profile was an intersection of the APIs available in two or more .NET implementations. So, for example, if you wanted to develop a library that could be used by Xamarin developers as well as Silverlight developers, you would have your library target the PCL profile that included both of those platforms. When writing your library, you would only be able to use the APIs that are available for all the platforms in the selected profile.

.NET Standard

With .NET Standard, Microsoft is working to create a better solution for the problem that PCLs were designed to solve. Think of .NET Standard as just a list of APIs that an implementation of .NET can support. As a library developer, if you target .NET Standard 1.2, your library can be used with any implementation of .NET that supports all the APIs defined for .NET Standard 1.2. Since PCLs will eventually be completely replaced by .NET Standard, it’s a good idea to get on that train!

See this page, https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard, for a more in-depth introduction to .NET Standard.

For our common (non-UI) code, we’ll add a new .NET Standard library to our Xamarin project.

Select Common Code

The version of .NET Standard we are targeting is available as part of the project’s properties.

.NET version

The native platform projects can now reference and use this library like a typical .NET class library project but we can also use this library in any application that is running on top of an implementation of .NET Standard 1.4. Xbox version of MyApp coming soon!

There are some known issues with using a .NET Standard library project within a Xamarin.Forms-based solution.

Dependency Injection

For code that is purely platform neutral, our new .NET Standard library will work well. However, sometimes, the implementation of an operation requires some platform-specific code. For example, if our file I/O code needs to obtain the path of the directory to write to, how to obtain that path will differ between iOS and Android (and Xbox). Dependency injection can provide a clean way to solve this problem.

First, we’ll define an interface (in the library) for the functionality that our .NET Standard library requires:

     public interface IStoragePathProvider
     {
       string GetPath();
     }

Each platform-specific project can then provide an implementation of the interface.

     public class StoragePathProvider : IStoragePathProvider
  { public string GetPath() { ... }   }

Finally, whenever our .NET Standard library needs the functionality provided by a native implementation, it can ask our dependency injection framework for an instance.

     var pathProvider = DependencyService.Get<IStoragePathProvider>(); 

This architecture means…

  1. We can trigger platform-specific functionality within our common library without taking a dependency on any platform-specific code.
  2. We avoid artifacts that are common in other cross-platform code sharing approaches (compiler directives, partial classes, etc.).
  3. If we use the library in a new type of project (e.g. Xbox), it will not require any modifications to the library itself (just an implementation of IStoragePathProvider in the new platform-specific project). This sounds like a software design principle. Gold star awarded if you said Open-Closed Principle (OCP)!

Conclusion

Working with the Xamarin platform is an exciting place to be. The acquisition of Xamarin by Microsoft has already resulted in better .NET platform integration and Visual Studio support, but, the journey is still in progress! The introduction of things like .NET Standard and .NET Core will continue to have an impact on how Xamarin applications are constructed. Just remember that as the technologies continue to evolve, they do not replace good software design practices and principles – they enable them. Learn about all the new things and use them in your projects if you can, but always try to be a good lazy programmer: just write it once or avoid writing it altogether if you can.


Author: Jason Bell, one of Accelebrate's Mobile Development instructors

In-Depth Mobile Training

For in-depth Mobile Development training, click here to view all of Accelebrate's Mobile training courses for you and your staff.

Request Pricing 




Learn faster

Our live, instructor-led lectures are far more effective than pre-recorded classes

Satisfaction guarantee

If your team is not 100% satisfied with your training, we do what's necessary to make it right

Learn online from anywhere

Whether you are at home or in the office, we make learning interactive and engaging

Multiple Payment Options

We accept check, ACH/EFT, major credit cards, and most purchase orders



Recent Training Locations

Alabama

Birmingham

Huntsville

Montgomery

Alaska

Anchorage

Arizona

Phoenix

Tucson

Arkansas

Fayetteville

Little Rock

California

Los Angeles

Oakland

Orange County

Sacramento

San Diego

San Francisco

San Jose

Colorado

Boulder

Colorado Springs

Denver

Connecticut

Hartford

DC

Washington

Florida

Fort Lauderdale

Jacksonville

Miami

Orlando

Tampa

Georgia

Atlanta

Augusta

Savannah

Hawaii

Honolulu

Idaho

Boise

Illinois

Chicago

Indiana

Indianapolis

Iowa

Cedar Rapids

Des Moines

Kansas

Wichita

Kentucky

Lexington

Louisville

Louisiana

New Orleans

Maine

Portland

Maryland

Annapolis

Baltimore

Frederick

Hagerstown

Massachusetts

Boston

Cambridge

Springfield

Michigan

Ann Arbor

Detroit

Grand Rapids

Minnesota

Minneapolis

Saint Paul

Mississippi

Jackson

Missouri

Kansas City

St. Louis

Nebraska

Lincoln

Omaha

Nevada

Las Vegas

Reno

New Jersey

Princeton

New Mexico

Albuquerque

New York

Albany

Buffalo

New York City

White Plains

North Carolina

Charlotte

Durham

Raleigh

Ohio

Akron

Canton

Cincinnati

Cleveland

Columbus

Dayton

Oklahoma

Oklahoma City

Tulsa

Oregon

Portland

Pennsylvania

Philadelphia

Pittsburgh

Rhode Island

Providence

South Carolina

Charleston

Columbia

Greenville

Tennessee

Knoxville

Memphis

Nashville

Texas

Austin

Dallas

El Paso

Houston

San Antonio

Utah

Salt Lake City

Virginia

Alexandria

Arlington

Norfolk

Richmond

Washington

Seattle

Tacoma

West Virginia

Charleston

Wisconsin

Madison

Milwaukee

Alberta

Calgary

Edmonton

British Columbia

Vancouver

Manitoba

Winnipeg

Nova Scotia

Halifax

Ontario

Ottawa

Toronto

Quebec

Montreal

Puerto Rico

San Juan