Copy an entire synced Realm

In our company, we use realm.io as mobile Database with the ROS Cloud to sync data between mobile devices and the server. Main advantage is, that we can build Apps in a fraction of time, without juggling with synchronization.

One of our main challenges was the disability to copy data from one realm to another. But there is still a good solution for this, even though you have to do a lot of coding for that.

Motivation

There are a lot of reasons, why copying realms is a really neat feature. First of all would be versioning your data. But it’s also very neat, when you have several instances (for development, testing etc.) to copy the whole data when you go productive or need some test data in development.

Challenge 1: generating the Schema

When we copy one realm to another, we actually don’t know the used types. We could include a library which contains the types, but then our “RealmCopy” will only work for a specific realm, which is really baloney. That’s as if you develop a copy-program, that can only copy text-files.

So we need to read the source realm, get the schema and create the same schema in the destination. In .Net we can open a realm dynamically, which is pretty cool, because this gives us a chance to get the information we need. Only problem – we can not create or change a schema on a dynamically opened realm.

Solution? We can create dynamic types, and open the destination realm, this will automatically create a schema on the destination realm. (It’s really a little bit awkward, but that’s currently the only chance in .Net – with Javascript, we can mutate the realm directly, but that’s probably due to the nature of that language)

RealmCopy

Open a realm as dynamic:

var username = "";
var password = "";
var realmUrl = "";
var realmName = "TestRealm";
var user = await User.LoginAsync(Credentials.UsernamePassword(username, password, false), new Uri(realmUrl));

var configuration = new FullSyncConfiguration(new Uri(realmName, UriKind.Relative), user)
{
IsDynamic = true
};
var srcRealm = await Realm.GetInstanceAsync(configuration);

now we can go through the scheme and create types:

var types = new List();
foreach (var scheme in schemasToProcess)
{
// create an assembly for our type
var assemblyName = new AssemblyName($"SomeAssemblyName{name}");
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
// create an module for the type
var moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
// get the typebuilder as
var typeBuilder = moduleBuilder.DefineType(name,
TypeAttributes.Public |
TypeAttributes.Class
, parent);
// add properties to type
foreach (var prop in schema)
{
var attributes = new List();
Type propType;
// woven property is needed, so Realm will add it to the destination schema
attributes.Add(typeof(WovenPropertyAttribute));
if (prop.IsPrimaryKey)
{
// add primary key attribute
attributes.Add(typeof(PrimaryKeyAttribute));
}
else if (prop.IsIndexed)
{
// add indexed attribute
attributes.Add(typeof(IndexedAttribute));
}

// get the property type
propType = prop.GetPropertyType(knownTypes);

// set required attribute, when its not nullable
if ((prop.Type & PropertyType.Nullable) != PropertyType.Nullable)
{
attributes.Add(typeof(RequiredAttribute));
}

// create the property
MyTypeBuilder.CreateProperty(typeBuilder, prop.Name, propType, attributes.ToArray());
}
types.Add(typeBuilder.CreateType());
}

In one of my previous blog posts I mentioned how to create types using the TypeBuilder, so I won’t code it out here.
The function GetPropertyType is an extension, it’s just a mapping of the Realm-PropertyType to a CLR type.
Now we can open the destination Realm:

var configuration = new FullSyncConfiguration(new Uri(realmName, UriKind.Relative), user);
configuration.ObjectClasses = types;
var destRealm = await Realm.GetInstanceAsync(configuration);

Challenge 2: copying the realm

This doesn’t actually seem to be a challenge. We go through all objects in source realm and copy it to a new RealmObject, which is created in destination. You can actually use our generated types to open the source realm and use straight reflection for mapping all properties. But be careful, if you did something wrong, you would probably mutate the source realm (what you might not want). You can stick to the dynamic Realm instead and use CallSiteCache to read the properties and reflection to set it to the destination object. (more infos)

Challenge 3: cascaded objects

An object may not only reference atomic types, but also have other RealmObjects as properties. It can even contain cycles. This is really tricky, I solved it by initially creating a TypeBuilder for each SchemaItem, then we can use this TypeBuilder as a PropertyType, without building the actual type. Creating objects can be done recursively, but keep track of the objects, you already created, so you can avoid cycles.

If you have any questions, feel free to ask. ..have fun coding.

Sponsored Post Learn from the experts: Create a successful blog with our brand new courseThe WordPress.com Blog

WordPress.com is excited to announce our newest offering: a course just for beginning bloggers where you’ll learn everything you need to know about blogging from the most trusted experts in the industry. We have helped millions of blogs get up and running, we know what works, and we want you to to know everything we know. This course provides all the fundamental skills and inspiration you need to get your blog started, an interactive community forum, and content updated annually.

Move Controls in Xamarin.Forms App with your finger

…or Mouse.. or Pen.. or nose, whatever you like. In WPF this is very easy accomplished, because Drag&Drop is a main UI feature in Windows. Each OS implements this feature slightly different, that’s why there is no such generic solution for all platforms. Microsoft proposes a solution called TouchEffect, which implements a specific Effect for each platform. (https://docs.microsoft.com/de-de/xamarin/xamarin-forms/app-fundamentals/effects/touch-tracking)

But there is still another and quite simple solution, you can use gestures (esp. the PanGesture) for that, with slight limitations.

MoveViewXamarin

The PanGesture

The PanGesture is actually a touch based Drag&Drop. You put the finger down on the screen and moved it around until you raise your finger. The PanGesture will always fire it’s event while the finger is moving around and will be quitted with the coordinates (0,0)

The Implementation

The implementation is quite simple, actually there are only a few lines of code:
1. when panning starts: save current Translation of View
2. while panning: set translation to the starting value + panning value
3. when panning finished: reset variable for starting value

Developers are lazy people, we don’t want to copy that implementation on every View. So the trick is, to use an attached property, so we can use it on every View and even bind it to a ViewModel.

The Code

public static class MoveView
{
    #region attached properties: CanMove
    public static readonly BindableProperty CanMoveProperty =
            BindableProperty.CreateAttached("CanMove", typeof(bool), typeof(View), false,
                propertyChanged: OnCanMoveChanged);

    private static void OnCanMoveChanged(BindableObject bindable, object oldValue, object newValue)
    {
        if ((bool)newValue && bindable is View view)
        {
            PanGestureRecognizer pangest = new PanGestureRecognizer();
            pangest.PanUpdated += Pangest_PanUpdated;
            view.GestureRecognizers.Add(pangest);
        }
    }
    public static bool GetCanMove(BindableObject bindable)
    {
        return (bool)bindable.GetValue(CanMoveProperty);
    }

    public static void SetCanMove(BindableObject bindable, bool value)
    {

        bindable.SetValue(CanMoveProperty, value);
    }
    #endregion

    // saves the translation state on start, it's okay to have it static
    // because we can only move one item at a time
    static Point? _translationStart = null;
    private static void Pangest_PanUpdated(object sender, PanUpdatedEventArgs e)
    {
        if (sender is View view)
        {
            if (e.TotalX == 0 && e.TotalY == 0)
            {
                // movement has end, reset
                _translationStart = null;
            }
            else
            {
                if (_translationStart == null)
                {
                    (view.Parent as Layout)?.RaiseChild(view);
                    _translationStart = new Point(view.TranslationX, view.TranslationY);
                }
                view.TranslationX = e.TotalX + _translationStart.Value.X;
                view.TranslationY = e.TotalY + _translationStart.Value.Y;
            }

        }
    }
}

Usage

 <Frame BorderColor="Red" BackgroundColor="Bisque"
                   dashboard:MoveView.CanMove="True"
                   HeightRequest="100" VerticalOptions="Center"
                 />

Limitations

– only when the parent is a layout, it will raise the View that is moved to the topmost position (only in respect to the parent, not overall)
– you can simply move the View outside of its parent, but then you will not be able to move it back in

Please feel free to use the code and change it as you like. If you find bugs, you may fix them. I would also be happy if you leave me some notes.

Xamarin.Forms FlowLayout

Motivation

I recently faced the challenge to add Items of different sizes to a Page on a Xamarin.Forms App. The result should be some kind of a Dashboard with Diagrams and info boxes on it. Some diagrams are smaller, some bigger.

The first thing, that came in mind, was a FlexLayout, but this looks a little bit odd to me, because the controls on the main axis share the same size in the secondary axis. That is okay if all controls have the same height or width, but this is not the case.

FlexLayout Xamarin.Forms App

But what I actually want is something like this:

FlowLayout - Xamarin.Forms App

It’s very tough to arrange the children of a Layout, when every control has a free size defined. To solve this problem, we need to divide the available area in uniform sections. Using this approach, each control can define it’s size in units, and will be placed on the next available free spot.

Simulator Screen Shot - iPhone 11 - 2020-02-20 at 22.30.18

The Algorithm

  1. The FlowLayout needs a UnitSizeRequested in pixels, we need to calculate how many items can fit vertically and horizontally based on a size of a unit. Afterwards we need to find the actual UnitWidth and UnitHeight so that the whole area of the control is used.
  2. There need to be two attached properties for the child elements, so each element can specify its HorizontalUnits and VerticalUnits.
  3. Finally we create an array as a representation of the FlowLayout so we can arrange the Controls on it.

The Code

using System;

using Xamarin.Forms;

namespace Dashboard
{
    public class FlowLayout : AbsoluteLayout
    {
        #region attached properties: HorizontalUnitsProperty
        public static readonly BindableProperty HorizontalUnitsProperty =
                BindableProperty.CreateAttached("HorizontalUnits", typeof(int), typeof(FlowLayout), 1);
        public static int GetHorizontalUnits(BindableObject view)
        {
            return (int)view.GetValue(HorizontalUnitsProperty);
        }

        public static void SetHorizontalUnits(BindableObject view, int value)
        {
            view.SetValue(HorizontalUnitsProperty, value);
        }
        #endregion
        #region attached properties: VerticalUnitsProperty
        public static readonly BindableProperty VerticalUnitsProperty =
                BindableProperty.CreateAttached("VerticalUnits", typeof(int), typeof(FlowLayout), 1);

        public static int GetVerticalUnits(BindableObject view)
        {
            return (int)view.GetValue(VerticalUnitsProperty);
        }

        public static void SetVerticalUnits(BindableObject view, int value)
        {
            view.SetValue(VerticalUnitsProperty, value);
        }
        #endregion

        #region properties
        public double UnitSizeRequested { get; set; } = 100;
        public double UnitWidth { get; private set; }
        public double UnitHeight { get; private set; }
        #endregion
       

        protected override void OnSizeAllocated(double width, double height)
        {
            // when the control allocates the size, we will arrange the children
            base.OnSizeAllocated(width, height);
            if (width>0 && height>0)
            {
                ArrangeChildren();
            }
        }

        

        public void ArrangeChildren()
        {
            // do the calculation (step 1)
            int horizontalUnitCount = (int)(Width / UnitSizeRequested);
            int verticalUnitCount = (int)(Height / UnitSizeRequested);
            bool[,] dashArray = new bool[horizontalUnitCount, verticalUnitCount];
            UnitWidth = UnitSizeRequested + (Width % UnitSizeRequested) / horizontalUnitCount;
            UnitHeight = UnitSizeRequested + (Height % UnitSizeRequested) / verticalUnitCount;
            foreach (var child in Children)
            {
                // for each child - find the 
                var rect = FindFreeRectangle(dashArray, GetHorizontalUnits(child), GetVerticalUnits(child));
                if (rect != null)
                {
                    AbsoluteLayout.SetLayoutBounds(child, rect.Value);
                }
                else
                {
                    // this control can not be placed ... so just skip it
                    AbsoluteLayout.SetLayoutBounds(child, new Rectangle(0, 0, 0, 0));
                }

            }
        }

        private Rectangle? FindFreeRectangle(bool[,] dashArray, int xCount, int yCount)
        {
            Rectangle res;
            for (int y = 0; y  dashArray.GetLength(1)
                )
                return false;

            for (int xx = x; xx < x + xCount; xx++)
            {
                for (int yy = y; yy < y + yCount; yy++)
                {
                    if (dashArray[xx, yy] == true)
                        return false;
                }
            }
            // now reserve fields
            for (var xx = x; xx < x + xCount; xx++)
            {
                for (var yy = y; yy < y + yCount; yy++)
                {
                    dashArray[xx, yy] = true;
                }
            }
            return true;
        }

      
    }
}

Caution: This code is not complete, perhaps you can not use it with the BindableLayout-Extension. Feel free to copy the code and change it as needed. Be careful in choosing the right UnitSizeRequested, a small unit will probably result in a rather bad performance.

Usage

<FlowLayout BackgroundColor="Black" >
        <Frame BorderColor="Yellow" BackgroundColor="Gray" CornerRadius="0" 
                FlowLayout.HorizontalUnits="1"
                FlowLayout.VerticalUnits="1"
                 />
        <Frame BorderColor="Gray" BackgroundColor="HotPink" CornerRadius="0" 
                FlowLayout.HorizontalUnits="1"
                FlowLayout.VerticalUnits="1"
                 />
        <Frame BorderColor="Blue" BackgroundColor="Honeydew" CornerRadius="0" 
                FlowLayout.HorizontalUnits="1"
                FlowLayout.VerticalUnits="1"
                 />
        <Frame BorderColor="Red" BackgroundColor="Bisque" CornerRadius="0" 
                FlowLayout.HorizontalUnits="4"
                FlowLayout.VerticalUnits="1"
                 />
        <Frame BorderColor="Green" BackgroundColor="CadetBlue" CornerRadius="0" 
                FlowLayout.HorizontalUnits="3"
                FlowLayout.VerticalUnits="3"
                 />
</FlowLayout>

Adding Themes to Xamarin.Forms App

I just want to make some short notes about themes in Xamarin.Forms Apps, since there are already a lot of tutorials available online, that go way deeper.

Themes
Themes are actually ResourceDictionaries. Each atomic type you use in your XAMLs and Styles, will be defined here. Types are f.e. Color, Double (for font sizes), etc.

<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="ShoppingList.Themes.DarkTheme">
    <Color x:Key="BackgroundColor">#333333</Color>
    <Color x:Key="TextColor">#eeeeee</Color>
    <Color x:Key="PlaceholderTextColor">#55ffffff</Color>
    <Color x:Key="ControlBackground">#111111</Color>
    <Color x:Key="ButtonBackgroundColor">#11ffffff</Color>
</ResourceDictionary>

Be sure to have a code behind file for your ResourceDictionary, that calls InitializeComponent(). Otherwise this will only work on UWP (without .NET Toolchain) and no other platforms.

Styles
In most cases the styles are not part of your themes, because using themes just makes you change the look of your pages and controls, not the styling of specific controls. Perhaps styles are using the resources, that you define in your theme. Be sure to use DynamicResource for linking to the key of the resource, otherwise you can not change themes during runtime. (Restart will be needed)

<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="ShoppingList.Resources.Styles">
    <Style TargetType="NavigationPage">
            <Setter Property="BackgroundColor" Value="{DynamicResource BackgroundColor}"/>
            <Setter Property="BarBackgroundColor" Value="{DynamicResource BackgroundColor}"/>
            <Setter Property="BarTextColor" Value="{DynamicResource TextColor}"/>
            
        </Style>
        <Style TargetType="Label">
            <Setter Property="TextColor" Value="{DynamicResource TextColor}" />
        </Style>
        <Style TargetType="Entry">
            <Setter Property="BackgroundColor" Value="{DynamicResource ControlBackground}" />
            <Setter Property="TextColor" Value="{DynamicResource TextColor}" />
            <Setter Property="PlaceholderColor" Value="{DynamicResource PlaceholderTextColor}" />
        </Style>
        <Style TargetType="Button">
            <Setter Property="TextColor" Value="{DynamicResource TextColor}" />
            <Setter Property="BackgroundColor" Value="{DynamicResource ButtonBackgroundColor}" />
            
        </Style>
</ResourceDictionary>

Changing the theme
Now you just need to add the following code to your App.xam.cs, then you can just call App.SetTheme(typeof(DarkTheme)) to change the theme during runtime.

Be sure to add all your style-ResourceDictionaries and a standard theme to your App.xaml in the Application.Resources-Section

internal static void SetTheme(Type themeType)
{
   Preferences.Set("Theme", themeType.FullName);
   var resDict = (ResourceDictionary)Activator.CreateInstance(themeType);
   App.Current.Resources.MergedDictionaries.Add(resDict); // this line replaces all keys of the current dictionary with the value of the selected dictionary, only the keys that are present in the selected dictionary will be replaced
}

In your “OnInitialize” method of your App.xaml.cs you can put the following code, to load the saved theme on startup:

if (Preferences.ContainsKey("Theme"))
{
   var themeTypeName = Preferences.Get("Theme",null);
   var themeType = Type.GetType(themeTypeName);
   if (themeType != null)
   {
      SetTheme(themeType);
   }
}

CSC : error CS1703: Multiple assemblies with equivalent identity have been imported (iOS)

I recently encountered a problem compiling my Xamarin.Forms iOS project. Everything worked well when testing the UWP App during development, but when I tried to test the iOS project, the compiler threw the following error:

CSC : error CS1703: Multiple assemblies with equivalent identity have been imported (iOS)'[..]\packages\system.reflection.emit\4.3.0\ref\netstandard1.1\System.Reflection.Emit.dll’ and ‘C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\ReferenceAssemblies\Microsoft\Framework\Xamarin.iOS\v1.0\Facades\System.Reflection.Emit.dll’. Remove one of the duplicate references.

 
Checking those two files mentioned, you’ll find out, that those have two different versions (nuget cache: 4.3.0, VisualStudio: 4.0.0), also the path (and file size) states, that the file from the VisualStudio folder is only a facade.

The solution is quite simple, just add a package reference to your project-file excluding all assets:

<PackageReference Include="System.Reflection.Emit" Version="4.3.0">
  <ExcludeAssets>all</ExcludeAssets>
</PackageReference>

.. just add it in an ItemGroup block with other package references and you solved that issue.

read and write properties on dynamic objects in .NET/C#

Ok, the headline sounds a little bit funny, because first of all, dynamic objects have no properties. Also you can not use reflection on a dynamic type, because it’s dynamic. What I actually want to do, is to access values of a dynamic object by its name – but I don’t know the name of the property on compile time, but during execution.

I want to do something like that:

dynamic obj = GetDynamicObject();
string myPropertyValue = DynamicExtension.GetValue(obj, "MyProperty");
DynamicExtension.SetValue(obj, "MyProperty", "some cool value");

So how can we do this? Reflection is not possible, and not all dynamic types impement IDictionary like ExpandoObject.

But how can we achieve this? By looking at the disassembled code, of a dynamic class, and the way it is accessed, we can find out, how we can access it ourself…

dynamic dynObj = new TestClass
{
  TestProperty = "Hello World",
  TestInt = 20
};
var val = dynObj.TestProperty;
dynObj.TestProperty = "Hello C#";

Because I don’t want to flood this post, I just copied the essentials from the IL. Basically there are 2 parts:
1. create a Binder
2. create a CallSite to execute the getter/setter.

// the getter
            var binder = Binder.GetMember(
                CSharpBinderFlags.None,
                "TestProperty",
                typeof(object),
                new CSharpArgumentInfo[] { 

 CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.NamedArgument, null)
                });

            var getter = CallSite<Func<CallSite,object,object>>.Create(binder);
            var val = getter.Target(getter,  dynObj);

// the setter
var setterBinder = Binder.SetMember(
    CSharpBinderFlags.None,
    "TestProperty",
    typeof(object),
    new CSharpArgumentInfo[] {
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) });
// the IL actually uses string as value type, but we use object here, to be more flexible
var setter = CallSite<Func<CallSite,object,object,object>>.Create(setterBinder);
setter.Target(setter, dynObj, "Hello C#");

So now just wrap it up to our two functions:

    public static class DynamicHelper
    {
        public static object GetValue(object obj, string name)
        {
            var binder = Binder.GetMember(
                        CSharpBinderFlags.None,
                        name,
                        typeof(object),
                        new CSharpArgumentInfo[] {
                            CSharpArgumentInfo.Create(
                                CSharpArgumentInfoFlags.NamedArgument,
                                null)
                        });

            var getter = CallSite<Func<CallSite,object,object>>.Create(binder);
            return getter.Target(getter, obj);
        }

        public static void SetValue(object obj, string name, object value)
        {
            var setterBinder = Binder.SetMember(
                CSharpBinderFlags.None,
                name,
                typeof(object),
                new CSharpArgumentInfo[] {
                  CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                  CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) });
            // the IL actually uses string as value type, but we use object here, to be more dynamic
            var setter = CallSite<Func<CallSite,object,object,object>>.Create(setterBinder);
            setter.Target(setter, obj, value);
        }
    }

C# Creating Types during runtime (.Net Core)

This is really fancy stuff, no one would probably never ever get along doing this. And I actually have no real straight forward “all day” use-case, I would ever recommend this for. But guess what, there is always an exception.

So why am I doing this?

My situation is the following: On one hand I have a database (actually a Realm.io database). I want to copy that Realm into another Realm, but I didn’t find a tool, doing that for me. Because that is an object oriented database, we need the model definitions right when opening the database, but I wanted to create a tool, to copy data from one realm to another, without actually knowing the class models at all. So there is a pretty neat construct called “DynamicRealm”, one can just open those by passing a parameter while opening the Realm called “IsDynamic”. Then I don’t need to have the actual classes in my code. When I then open an existing Realm, it shows me all information about the schema, that is stored in the database (properties, attributes, etc.)…

So far, so good, .. I can read data. But my destination Realm is absolutely blank, no schema, no data. And in .NET there is no method implemented to create my own schema. There is only one thing I can do – adding Types while opening the Realm, and Realm will take care of creating the schema. So I need to impement type-creation from the schema during runtime. 

Creating the type during runtime

But before we create a type, we need to create an Assembly and Module, that type is going to be in. Be careful to use names, that aren’t already used. There are 3 Builders we use from the assembly System.Reflection.Emit : AssemblyBuilder, ModuleBuilder, TypeBuilder . In fact this part is pretty easy:

var parent = typeof(BaseClass); // the type of the baselcass for this type (can be null)
var name = "MyCoolTypeName"; // name of the new type

// 1. create assembly name
var assemblyName = new AssemblyName($"SomeAssemblyName{name}");
// 2. create the assembly builder
AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
// 3. that is needed to create a module builder
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
// 4. and finally our TypeBuilder (a public class)
TypeBuilder tb = moduleBuilder.DefineType(name,
TypeAttributes.Public |
TypeAttributes.Class
, parent);
Type type = tb.CreateType(); // of type Type, we can even create instances of that type

But when we want to create a real POCO we also need to add some properties to that type.

Add properties to the created Type (TypeBuilder)

This is not as easy, as it sounds like. We have to be aware, what is actually needed to create a property:
1. a backing field
2. a get method
3. a set method
Since we are in runtime mode, we need to create the method bodys in IL (which is the byte code used by .NET), so we cannot use plain C#.
(Be careful: all this can only run on systems with JIT compiler, so you cannot do that in UWP (with .Net Toolchain active) or iOS, Mono should be fine, but I didn’t test it yet)

So how to find out what IL to use? Just create a TestClass and produce some IL (I prefer using dotPeek from JetBrains):

.method public hidebysig specialname instance string
    get_Text() cil managed
  {
    IL_0000: ldarg.0      // this
    IL_0001: ldfld        string RealmCopy.TestClass::'_backingField'
    IL_0006: ret

  } // end of method TestClass::get_Text

  .method public hidebysig specialname instance void
    set_Text(
      string 'value'
    ) cil managed
  {
    IL_0000: ldarg.0      // this
    IL_0001: ldarg.1      // 'value'
    IL_0002: stfld        string RealmCopy.TestClass::'_backingField'
    IL_0007: ret

  } // end of method TestClass::set_Text

After that, we can just write down the code for adding a property to the TypeBuilder:

public static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
{
   if (propertyType == null) // when the propertytype is null, we assume, it's the Type itself (so we set it to the TypeBuilder)
   {
       propertyType = tb;
   }

   if (propertyType == typeof(IList&amp;amp;lt;&amp;amp;gt;)) // same thing here for a IList with no generic type parameter -&amp;amp;gt; we assume it's the type (we could probably do that for every generic type without type parameter)
   {
       propertyType = propertyType.MakeGenericType(tb);
   }

   FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private); //creates the backing field
   PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);

   //get method
   MethodBuilder getPropMthBldr = tb.DefineMethod(
      "get_" + propertyName
      ,MethodAttributes.Public
       | MethodAttributes.SpecialName
       | MethodAttributes.HideBySig
      , /*returnType*/ propertyType
      , /*parameter types*/ Type.EmptyTypes); // see IL for the right MethodAttributes
   ILGenerator getIl = getPropMthdBldr.GetILGenerator();
   // create the code in the get method
   getIl.Emit(OpCodes.Ldarg_0); //this
   getIl.Emit(OpCodes.Ldfld, fieldBuilder); //backingfield
   getIl.Emit(OpCodes.Ret); 

   // set method
   MethodBuilder setPropMthdBldr =
   tb.DefineMethod(
      "set_" + propertyName,
      MethodAttributes.Public
       | MethodAttributes.SpecialName
       | MethodAttributes.HideBySig
      , /*returnType*/ null
      , /*parameter types*/ new[] { propertyType }); // see IL for the right MethodAttributes

   ILGenerator setIl = setPropMthdBldr.GetILGenerator();
   // create the code in the set method
   setIl.Emit(OpCodes.Ldarg_0); //this
   setIl.Emit(OpCodes.Ldarg_1); // 'value'
   setIl.Emit(OpCodes.Stfld, fieldBuilder); // backingfield

   setIl.Emit(OpCodes.Nop);
   setIl.Emit(OpCodes.Ret);

   // add methods to the propertyBuilder
   propertyBuilder.SetGetMethod(getPropMthdBldr);
   propertyBuilder.SetSetMethod(setPropMthdBldr);
}

Problem with ResourceDictionary in Xamarin Forms .Net Native

Last week a colleague had the idea, to split the Resources, that we have defined in App.xaml in several ResourceDictionaries. Since our App.xaml has grown to over 400 lines, we thought this would be a very good idea, and did it as always:

 <Application.Resources>
        <ResourceDictionary xmlns:local="clr-namespace:TestResources">
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/Resources/Buttons.xaml" />
                <ResourceDictionary Source="/Resources/Labels.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

Looks good, and when we were testing the App, it worked well. But as soon, as we wanted to ship the App to our customer, it totally crashed during start up. What was the difference? We always test Debug builds, but without .Net Native
Toolchain active, but for shipping, we made a Release build with .Net Native builds activated.

The following error occured:

Unhandled exception at 0x05B6B264 (Windows.UI.Xaml.dll) in TestResources.UWP.exe: 0xC000027B: Anwendungsinterne Ausnahme (parameters: 0x0B477CF8, 0x00000003).

In the output window we see a lot of error messages:

Unhandled exception at 0x05B4B264 (Windows.UI.Xaml.dll) in TestResources.UWP.exe: 0xC000027B: internal error(parameters: 0x0B44D9B0, 0x00000003).

Unhandled exception at 0x777AF989 (combase.dll) in TestResources.UWP.exe: 0xC0000602: Ein sofortiger Ausnahmefehler ist aufgetreten. Die Ausnahmehandler werden nicht aufgerufen, und der Prozess wird sofort beendet.

Unhandled exception at 0x77627ED3 (combase.dll) in TestResources.UWP.exe: 0xC0000005: Access violation reading location 0x00000008.

I am not quite sure, why this happens but the solution is quite simple:

  • Add a code behind file (in our case Buttons.cs).
  • In the constructor, call “InitializeComponent()”.
  • Now we can include the ResourceDictionary directly in the App.xaml
  • In our case the Buttons.xaml.cs looks like this:

       public partial class Buttons : ResourceDictionary
        {
            public Buttons()
            {
                InitializeComponent();
            }
        }
    

    ..and the App.xaml

    <Application.Resources>
            <ResourceDictionary xmlns:local="clr-namespace:TestResources">
                <ResourceDictionary.MergedDictionaries>
                    <local:Buttons />
                    <!--<ResourceDictionary Source="/Resources/Buttons.xaml" />-->
                    <!--<ResourceDictionary Source="/Resources/Labels.xaml" />-->
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
        </Application.Resources>
    

    If you have a clue, why we need to go this way, just leave me a comment.

    Error 0xC000041D using GetCallingAssembly()

    Reflection is very cool, the meta data system of .Net is pretty cool. You can create objects of a given class, without knowing it at compile time, by just looking it up and instantiating it using reflection. But how can I look up a type? Some times you only know the name of a type you want to create, without knowing the correct assembly. Let’s say we have an assembly, that holds a service implementation to create a object:

    class MyService
    {
      object GetObject(string typeName)
      {
      }
    }
    

    The class we want to create, is in the assembly from where that function gets called. That is ok, but we don’t know that assembly at compile time, we can only find it out, when the function gets called. But how?

    The regular solution would be, to use System.Reflection.Assembly.GetCallingAssembly(). But when we do this in .Net Nativ, we get an exception at runtime:

    Unhandled exception at 0x78A7B264 (Windows.UI.Xaml.dll) in BlankApp3.UWP.exe: 0xC000027B

    I think this is a bug within the .Net native compiler. But how can we find a workaround for that problem?

    1. using a fully qualified type name

    object GetObject(string typeName)
    {
      var type = Type.GetType(typeName);
      return Activator.CreateInstance(type);
    }
    

    You can then actually use the complete name, including the namespace, when calling the function. (Something like: GetObject(“BlankApp3.Views.MainPage”)), so it’s not possible to lookup a type by name. But for our use case, it is enough.

    2. lookup the assembly by name

    object GetObject(string assemblyName, string typeName)
    {
      var assemblies = AppDomain.CurrentDomain.GetAssemblies();
      var assembly = assemblies.FirstOrDefault(asm => 
                     asm.GetName().Name.Equals(assemblyName));
      var type = assembly.GetTypes().FirstOrDefault(t => 
                 t.Name.Equals(typeName));
      return Activator.CreateInstance(type);
    }
    

    This is the most flexible solution in our case (but it takes more time). You can even look through all loaded assemblies, and find types by name. Please be aware that there is another bug, preventing you from getting all types from all loaded assemblies (the solution can be found on stackoverflow).