Sunday, July 17, 2011

Dynamically adding RaisePropertyChanged to MVVM Light ViewModels using Mono Cecil

Introduction

A few days ago, I wrote an article about dynamically modifying MVVM Light ViewModels using Reflection.Emit. The same can be done with the more powerful Mono Cecil library. Mono Cecil can both create assemblies at runtime and modify existing ones. The latter allows to modify post-compilation the generated MSIL code. This is helpful on platforms like Windows Phone 7; that do not allow dynamic runtime loading of assemblies.

In this article, I will show you how we can generate the same proxies as in the Reflection.Emit example. In a latter example, I will show you how to update assemblies post compilation for use on Windows Phone 7. If you have not read my previous article, I recommend that you read it first.
Implementation

Mono Cecil can be easily retrieved using NuGet.

The implementation is almost the same; similar concepts classes are used. I will not explain them in detail, but just show the modified example. (If you would have questions, feel free to drop a comment Glimlach).

public static class CecilViewModelFactory
{
    public static T CreateInstance<T>()
        where T : ViewModelBase
    {
        Type vmType = typeof(T);

        ModuleDefinition module = ModuleDefinition.CreateModule("CecilDynamicTestPieter", ModuleKind.Dll);
        TypeReference baseTypeReference = module.Import(vmType);
        TypeDefinition typeDefinition =
            new TypeDefinition(vmType.Namespace, "Smart" + vmType.Name, TypeAttributes.Public, baseTypeReference);
        module.Types.Add(typeDefinition);
        MethodReference raisePropertyChangedMethod = module.Import(typeof(ViewModelBase).GetMethod("RaisePropertyChanged",
            Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance, null, new Type[] { typeof(string) }, null));

        // Create default constructor
        typeDefinition.Methods.Add(CreateDefaultConstructor(module, vmType));

        foreach (Reflection.PropertyInfo propertyInfo in FindNotifyPropertyChangCandidates<T>())
        {
            ILProcessor processor;

            // Get set method of base type
            MethodReference setMethodReference = module.Import(propertyInfo.GetSetMethod());

            PropertyDefinition propertyDefinition = new PropertyDefinition(propertyInfo.Name,
                PropertyAttributes.None, module.Import(propertyInfo.PropertyType));
            typeDefinition.Properties.Add(propertyDefinition);


Read more: Windows Phone 7
QR: dynamically-adding

Posted via email from Jasper-Net