(X) Hide this
    • Login
    • Join
      • Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows Store apps with XAML and HTML: Writing C# components for the Windows Store apps

(1 votes)
Andrea Boschin
>
Andrea Boschin
Joined Nov 17, 2009
Articles:   91
Comments:   9
More Articles
0 comments   /   posted on May 13, 2013
Categories:   Windows 8

Tweet

In the last article in this series, I've discussed about the use of a much more reliable solution to write effective code in Javascript, using Typescript. When you deal with solutions that are more than a simple exercise, this need becomes strong because you have the requirement of making your code strong and effective in the shortest time and in this scenario Javascript is not a safe way.
In this scenario, the Windows Store apps, let you to create reusable components, called "Windows Runtime Component", that may be written using C# or C++. These components may be used directly from your HTML or also XAML application but they have a number of limitations that comes from this sharing between different technologies.

Why to build Windows Runtime Component

The first step in the choice of creating a Windows Runtime Component is to find the good reason to do it. There are two parts in this decision. The first is the need of share your code between a HTML5/Javascript and XAML/C#. If you are working with XAML and C# on the front-end the best choice is to rely on a simple class library, as usual with the .NET Framework. The class library project is a reusable container that you can easily use from your XAML application overriding a number of limitations that instead apply to Windows Runtime Components. Instead if you already know that your component should be used with both the languages, the WinRT component is the good way.

The other part of the decision instead, comes from the objective advantages that a Windows Runtime Component brings to you. These can be resumed in the following points:

  1. Reuse of existing code wrote in C# or C++
  2. Reuse of your team skills in the above languages (but why don't use them for the whole app?)
  3. Protecting your code from unwanted disclosure

The last point may be a key for your choice, but you have always to remember that also in C# is compiled to IL, it does not suffice to fully protect your code because its reverse engineering is far to be difficult. In this case your sole choice is to work in C++ that compiles in native code and is much more difficult to be reverse engineered.

So, definitely you have always to fully weigh all your ways, having clear in mind your present requirements and skills together with the view for your future needs that may change the way you write code today to improve your speed later.

Creating a component

The process of creating a component is really simple as it be in choosing a template in Visual Studio. In both the "Visual C#" and "Visual C++" nodes of the "New project" dialog there is a "Windows Runtime Component" template that you can use to create the skeleton for your new component. In the figure you can see the dialog for the C# component:

image

At the first sight the project that is created seems exactly equal to a normal class library, indeed, the references and the structure of the project are the same. The difference becomes evident if you open a property window for the project and you watch at the "output type" dropdown list.  

This drop down list reports "Windows Runtime Component". In this configuration, the project is set to silently create a COM component with your code and a special file called "winmd" that describes the types exposed by this component. The WinMD file is an assembly (it follows the specification of the CLR and you may open it using ildasm) that contains only the description of the structure of this component. It is made to make it available to the Javascript an C# (or VB.NET) applications that use it.

An important component that is published as a winmd file is the Windows.winmd assembly. It takes all the descriptions of the Windows.* components that you usually use during the development of a Windows Store App.

Interesting to note, these kind of component are also available in the Windows Phone 8. Infact, thanks to the common kernel that is part of the phone runtime, it shared about 2800 on 11000 members that is part of the WinRT. This let you create common components that are shared between the Windows 8 and Windows Phone 8. It is particularly indicated for common algorithms and business logic.

Thanks to the Windows Runtime, the winmd files are used to dynamically create a projection of the underlying component to make it available to your elective language. The projection layer is smart enough to adapt the published component to the target language. As an example take the following type exposed in a WinRT component: 

   1: public sealed class Earthquake
   2: {
   3:     public string ID { get; set; }
   4:     public DateTimeOffset EpicenterDate { get; set; }
   5:     public double Magnitude { get; set; }
   6:     public double Latitude { get; set; }
   7:     public double Longitude { get; set; }
   8: }

When you reference this class from a C# application it is projected as it is a normal C# type so the name of the properties respect the casing that is used in the component's code:

   1: var eq = new Elite.EarthquakeAlerts.Model.Earthquake();
   2: var date = eq.EpicenterDate;

If you reference the same class from a Javascript application, the projection layer adapt the code to the target language, so it exports the type with the same casing but it makes the properties camel-cased as it is use to do in Javascript:

   1: var eq = new Elite.EarthquakeAlerts.Model.Earthquake();
   2: var date = eq.epicenterDate;

Limitations

Given that the projection layer have to do it works to smooth the edges of a components and make it much more similar to the consumer expectations, it is logic to expect that it has also to follow a minimum common denominator that apply to all the languages. And this is effectively true so you have to expect some limitations to the exposed types. These limitations apply to the types that are made available as public, so they have to be used potentially by all the languages.

To fully understand the nature of these limitations you may do a simple but interesting exercise. Take a simple class library and put together a bunch of classes inside of it. In my case I've taken a library that I've previously created to export a model and a toolset to access the USGS earthquake service I've often used in my examples. The original library contains a series of classes representing the response of the remote service, the classes used to interact with the service and a model that is exposed to make available the response to the consumer. These classes respect a hierarchy that I've used to expose the geographical information.

image

Once the classes are ready and they compiles as a class library, simple go to the project properties and change the "output type" to "Windows Runtime Component". It is exactly what I've done with my first try of a component, and is resulted in an discomforting series of errors that rapidly cut my enthusiasm. All these errors comes from the limits that it imposes the sharing between languages. They are generically caused by the following reasons:

  1. You exposed a non sealed class. All the classes that is marked as public must be also "sealed". At a deepest analysis this means that you cannot expose classes that inherit from other types when they are not interfaces. This is probably the worst and most annoying limitation that in my case cut the great part of the original library.
  2. You are using a type that is not supported by WinRT. As an example some types in my library returns "DateTime" and it is not supported by WinRT. To make it understandable by Javascript you have to change them to DateTimeOffset directly exposing the timezone.
  3. You have used a generic type. WinRT does not support generic types other than a restricted set of interfaces like IEnumerable<T>, IMap<T> and IVector<T>. All your types have to implements these interfaces or cannot be generic.
  4. You have returned a Task<T> from a method, trying to make it asynchronous to be used with asymc/await keywords in C#. This is not supported by WinRT also if asynchronicity is obviously supported. To override this limitation you have to convert a Task<T> to IAsyncOperation<T> using the AsAsyncOperation<T>() method on this class.

All these are the most common pitfalls that usually affects the developers the first time they try to write a WinRT component. You have to accept them and write having clear in mind that your work, under these limitations, would be available to multiple platforms so they becomes understandable and acceptable. At the end of an hard refactoring here is what it remains of my original library:

image

Conclusions

It is clear that developing an effective Windows Runtime Component is something that may become frustrating if you do not have a good reason to accept all these limits. Only being aware of the benefit of code reuse you can give up with the full set of tools you are use with C# libraries. The best approach to me is to always have a public set of classes that wraps a well structured set of types hidden to the consumer. In this private set you can use all the bullets you know you have with C#. Then, when it is the time to push the results out to the consumer, you have to rely on a simplified and compatible structure that works as an interface between the two separated worlds.


Subscribe

Comments

No comments

Add Comment

Login to comment:
  *      *       

From this series