IntroductionA 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.
ImplementationMono 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:
ImplementationMono 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: