public static IEnumerable <Instruction> PushConvertedValue(this ValueNode node, ILContext context, TypeReference targetTypeRef, TypeReference typeConverter, IEnumerable <Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; var str = (string)node.Value; //If there's a [TypeConverter], use it if (typeConverter != null) { var isExtendedConverter = typeConverter.ImplementsInterface(module.Import(typeof(IExtendedTypeConverter))); var typeConverterCtor = typeConverter.Resolve().Methods.Single(md => md.IsConstructor && md.Parameters.Count == 0); var typeConverterCtorRef = module.Import(typeConverterCtor); var convertFromInvariantStringDefinition = isExtendedConverter ? module.Import(typeof(IExtendedTypeConverter)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 2) : typeConverter.Resolve() .AllMethods() .FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 1); var convertFromInvariantStringReference = module.Import(convertFromInvariantStringDefinition); yield return(Instruction.Create(OpCodes.Newobj, typeConverterCtorRef)); yield return(Instruction.Create(OpCodes.Ldstr, node.Value as string)); if (isExtendedConverter) { foreach (var instruction in pushServiceProvider) { yield return(instruction); } } yield return(Instruction.Create(OpCodes.Callvirt, convertFromInvariantStringReference)); if (targetTypeRef.IsValueType && unboxValueTypes) { yield return(Instruction.Create(OpCodes.Unbox_Any, module.Import(targetTypeRef))); } //ConvertFrom returns an object, no need to Box yield break; } var originalTypeRef = targetTypeRef; var isNullable = false; MethodReference nullableCtor = null; if (targetTypeRef.Resolve().FullName == "System.Nullable`1") { var nullableTypeRef = targetTypeRef; targetTypeRef = ((GenericInstanceType)targetTypeRef).GenericArguments[0]; isNullable = true; nullableCtor = originalTypeRef.GetMethods(md => md.IsConstructor && md.Parameters.Count == 1, module).Single().Item1; nullableCtor = nullableCtor.ResolveGenericParameters(nullableTypeRef, module); } //Obvious Built-in conversions if (targetTypeRef.Resolve().BaseType != null && targetTypeRef.Resolve().BaseType.FullName == "System.Enum") { yield return(Instruction.Create(OpCodes.Ldc_I4, ParseEnum(targetTypeRef, str, node))); } else if (targetTypeRef.FullName == "System.Char") { yield return(Instruction.Create(OpCodes.Ldc_I4, Char.Parse(str))); } else if (targetTypeRef.FullName == "System.Byte") { yield return(Instruction.Create(OpCodes.Ldc_I4, Byte.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Int16") { yield return(Instruction.Create(OpCodes.Ldc_I4, Int16.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Int32") { yield return(Instruction.Create(OpCodes.Ldc_I4, Int32.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Int64") { yield return(Instruction.Create(OpCodes.Ldc_I8, Int64.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Single") { yield return(Instruction.Create(OpCodes.Ldc_R4, Single.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Double") { yield return(Instruction.Create(OpCodes.Ldc_R8, Double.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Boolean") { if (Boolean.Parse(str)) { yield return(Instruction.Create(OpCodes.Ldc_I4_1)); } else { yield return(Instruction.Create(OpCodes.Ldc_I4_0)); } } else if (targetTypeRef.FullName == "System.TimeSpan") { var ts = TimeSpan.Parse(str, CultureInfo.InvariantCulture); var ticks = ts.Ticks; var timeSpanCtor = module.Import(typeof(TimeSpan)) .Resolve() .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1); var timeSpanCtorRef = module.Import(timeSpanCtor); yield return(Instruction.Create(OpCodes.Ldc_I8, ticks)); yield return(Instruction.Create(OpCodes.Newobj, timeSpanCtorRef)); } else if (targetTypeRef.FullName == "System.DateTime") { var dt = DateTime.Parse(str, CultureInfo.InvariantCulture); var ticks = dt.Ticks; var dateTimeCtor = module.Import(typeof(DateTime)) .Resolve() .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1); var dateTimeCtorRef = module.Import(dateTimeCtor); yield return(Instruction.Create(OpCodes.Ldc_I8, ticks)); yield return(Instruction.Create(OpCodes.Newobj, dateTimeCtorRef)); } else if (targetTypeRef.FullName == "System.String" && str.StartsWith("{}", StringComparison.Ordinal)) { yield return(Instruction.Create(OpCodes.Ldstr, str.Substring(2))); } else if (targetTypeRef.FullName == "System.String") { yield return(Instruction.Create(OpCodes.Ldstr, str)); } else if (targetTypeRef.FullName == "System.Object") { yield return(Instruction.Create(OpCodes.Ldstr, str)); } else { yield return(Instruction.Create(OpCodes.Ldnull)); } if (isNullable) { yield return(Instruction.Create(OpCodes.Newobj, module.Import(nullableCtor))); } if (originalTypeRef.IsValueType && boxValueTypes) { yield return(Instruction.Create(OpCodes.Box, module.Import(originalTypeRef))); } }
public IEnumerable <Instruction> ProvideValue(IElementNode node, ModuleDefinition module, ILContext context, out TypeReference memberRef) { var typeNode = node.Properties[new XmlName("", "Type")] as IElementNode; var typeTypeRef = context.TypeExtensions[typeNode]; var n = node.CollectionItems.Count; var instructions = new List <Instruction>(); instructions.Add(Instruction.Create(OpCodes.Ldc_I4, n)); instructions.Add(Instruction.Create(OpCodes.Newarr, typeTypeRef)); memberRef = typeTypeRef.MakeArrayType(); for (var i = 0; i < n; i++) { var vardef = context.Variables[node.CollectionItems[i] as IElementNode]; if (typeTypeRef.IsValueType) { instructions.Add(Instruction.Create(OpCodes.Dup)); instructions.Add(Instruction.Create(OpCodes.Ldc_I4, i)); instructions.Add(Instruction.Create(OpCodes.Ldelema, typeTypeRef)); instructions.Add(Instruction.Create(OpCodes.Ldloc, vardef)); if (vardef.VariableType == module.TypeSystem.Object) { instructions.Add(Instruction.Create(OpCodes.Unbox_Any, module.ImportReference(typeTypeRef))); } instructions.Add(Instruction.Create(OpCodes.Stobj, typeTypeRef)); } else { instructions.Add(Instruction.Create(OpCodes.Dup)); instructions.Add(Instruction.Create(OpCodes.Ldc_I4, i)); instructions.Add(Instruction.Create(OpCodes.Ldloc, vardef)); instructions.Add(Instruction.Create(OpCodes.Stelem_Ref)); } } return(instructions); }
public static IEnumerable <Instruction> PushConvertedValue(this ValueNode node, ILContext context, TypeReference targetTypeRef, TypeReference typeConverter, IEnumerable <Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; var str = (string)node.Value; //If the TypeConverter has a ProvideCompiledAttribute that can be resolved, shortcut this var compiledConverterName = typeConverter?.GetCustomAttribute(module.ImportReference(typeof(ProvideCompiledAttribute)))?.ConstructorArguments?.First().Value as string; Type compiledConverterType; if (compiledConverterName != null && (compiledConverterType = Type.GetType(compiledConverterName)) != null) { var compiledConverter = Activator.CreateInstance(compiledConverterType); var converter = typeof(ICompiledTypeConverter).GetMethods().FirstOrDefault(md => md.Name == "ConvertFromString"); var instructions = (IEnumerable <Instruction>)converter.Invoke(compiledConverter, new object[] { node.Value as string, context, node as BaseNode }); foreach (var i in instructions) { yield return(i); } if (targetTypeRef.IsValueType && boxValueTypes) { yield return(Instruction.Create(OpCodes.Box, module.ImportReference(targetTypeRef))); } yield break; } //If there's a [TypeConverter], use it if (typeConverter != null) { var isExtendedConverter = typeConverter.ImplementsInterface(module.ImportReference(typeof(IExtendedTypeConverter))); var typeConverterCtor = typeConverter.Resolve().Methods.Single(md => md.IsConstructor && md.Parameters.Count == 0 && !md.IsStatic); var typeConverterCtorRef = module.ImportReference(typeConverterCtor); var convertFromInvariantStringDefinition = isExtendedConverter ? module.ImportReference(typeof(IExtendedTypeConverter)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 2) : typeConverter.Resolve() .AllMethods() .FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 1); var convertFromInvariantStringReference = module.ImportReference(convertFromInvariantStringDefinition); yield return(Instruction.Create(OpCodes.Newobj, typeConverterCtorRef)); yield return(Instruction.Create(OpCodes.Ldstr, node.Value as string)); if (isExtendedConverter) { foreach (var instruction in pushServiceProvider) { yield return(instruction); } } yield return(Instruction.Create(OpCodes.Callvirt, convertFromInvariantStringReference)); if (targetTypeRef.IsValueType && unboxValueTypes) { yield return(Instruction.Create(OpCodes.Unbox_Any, module.ImportReference(targetTypeRef))); } //ConvertFrom returns an object, no need to Box yield break; } var originalTypeRef = targetTypeRef; var isNullable = false; MethodReference nullableCtor = null; if (targetTypeRef.Resolve().FullName == "System.Nullable`1") { var nullableTypeRef = targetTypeRef; targetTypeRef = ((GenericInstanceType)targetTypeRef).GenericArguments[0]; isNullable = true; nullableCtor = originalTypeRef.GetMethods(md => md.IsConstructor && md.Parameters.Count == 1, module).Single().Item1; nullableCtor = nullableCtor.ResolveGenericParameters(nullableTypeRef, module); } var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(targetTypeRef, module); //Obvious Built-in conversions if (targetTypeRef.Resolve().BaseType != null && targetTypeRef.Resolve().BaseType.FullName == "System.Enum") { yield return(PushParsedEnum(targetTypeRef, str, node)); } else if (targetTypeRef.FullName == "System.Char") { yield return(Instruction.Create(OpCodes.Ldc_I4, Char.Parse(str))); } else if (targetTypeRef.FullName == "System.SByte") { yield return(Instruction.Create(OpCodes.Ldc_I4, SByte.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Int16") { yield return(Instruction.Create(OpCodes.Ldc_I4, Int16.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Int32") { yield return(Instruction.Create(OpCodes.Ldc_I4, Int32.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Int64") { yield return(Instruction.Create(OpCodes.Ldc_I8, Int64.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Byte") { yield return(Instruction.Create(OpCodes.Ldc_I4, Byte.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.UInt16") { yield return(Instruction.Create(OpCodes.Ldc_I4, unchecked ((int)UInt16.Parse(str, CultureInfo.InvariantCulture)))); } else if (targetTypeRef.FullName == "System.UInt32") { yield return(Instruction.Create(OpCodes.Ldc_I4, UInt32.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.UInt64") { yield return(Instruction.Create(OpCodes.Ldc_I8, unchecked ((long)UInt64.Parse(str, CultureInfo.InvariantCulture)))); } else if (targetTypeRef.FullName == "System.Single") { yield return(Instruction.Create(OpCodes.Ldc_R4, Single.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Double") { yield return(Instruction.Create(OpCodes.Ldc_R8, Double.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Boolean") { if (Boolean.Parse(str)) { yield return(Instruction.Create(OpCodes.Ldc_I4_1)); } else { yield return(Instruction.Create(OpCodes.Ldc_I4_0)); } } else if (targetTypeRef.FullName == "System.TimeSpan") { var ts = TimeSpan.Parse(str, CultureInfo.InvariantCulture); var ticks = ts.Ticks; var timeSpanCtor = module.ImportReference(typeof(TimeSpan)) .Resolve() .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1); var timeSpanCtorRef = module.ImportReference(timeSpanCtor); yield return(Instruction.Create(OpCodes.Ldc_I8, ticks)); yield return(Instruction.Create(OpCodes.Newobj, timeSpanCtorRef)); } else if (targetTypeRef.FullName == "System.DateTime") { var dt = DateTime.Parse(str, CultureInfo.InvariantCulture); var ticks = dt.Ticks; var dateTimeCtor = module.ImportReference(typeof(DateTime)) .Resolve() .Methods.FirstOrDefault(md => md.IsConstructor && md.Parameters.Count == 1); var dateTimeCtorRef = module.ImportReference(dateTimeCtor); yield return(Instruction.Create(OpCodes.Ldc_I8, ticks)); yield return(Instruction.Create(OpCodes.Newobj, dateTimeCtorRef)); } else if (targetTypeRef.FullName == "System.String" && str.StartsWith("{}", StringComparison.Ordinal)) { yield return(Instruction.Create(OpCodes.Ldstr, str.Substring(2))); } else if (targetTypeRef.FullName == "System.String") { yield return(Instruction.Create(OpCodes.Ldstr, str)); } else if (targetTypeRef.FullName == "System.Object") { yield return(Instruction.Create(OpCodes.Ldstr, str)); } else if (targetTypeRef.FullName == "System.Decimal") { decimal outdecimal; if (decimal.TryParse(str, NumberStyles.Number, CultureInfo.InvariantCulture, out outdecimal)) { var vardef = new VariableDefinition(context.Body.Method.Module.ImportReference(typeof(decimal))); context.Body.Variables.Add(vardef); //Use an extra temp var so we can push the value to the stack, just like other cases // IL_0003: ldstr "adecimal" // IL_0008: ldc.i4.s 0x6f // IL_000a: call class [mscorlib]System.Globalization.CultureInfo class [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture() // IL_000f: ldloca.s 0 // IL_0011: call bool valuetype [mscorlib]System.Decimal::TryParse(string, valuetype [mscorlib]System.Globalization.NumberStyles, class [mscorlib]System.IFormatProvider, [out] valuetype [mscorlib]System.Decimal&) // IL_0016: pop yield return(Instruction.Create(OpCodes.Ldstr, str)); yield return(Instruction.Create(OpCodes.Ldc_I4, 0x6f)); //NumberStyles.Number var getInvariantInfo = context.Body.Method.Module.ImportReference(typeof(CultureInfo)) .Resolve() .Properties.FirstOrDefault(pd => pd.Name == "InvariantCulture") .GetMethod; var getInvariant = context.Body.Method.Module.ImportReference(getInvariantInfo); yield return(Instruction.Create(OpCodes.Call, getInvariant)); yield return(Instruction.Create(OpCodes.Ldloca, vardef)); var tryParseInfo = context.Body.Method.Module.ImportReference(typeof(decimal)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "TryParse" && md.Parameters.Count == 4); var tryParse = context.Body.Method.Module.ImportReference(tryParseInfo); yield return(Instruction.Create(OpCodes.Call, tryParse)); yield return(Instruction.Create(OpCodes.Pop)); yield return(Instruction.Create(OpCodes.Ldloc, vardef)); } else { yield return(Instruction.Create(OpCodes.Ldc_I4_0)); var decimalctorinfo = context.Body.Method.Module.ImportReference(typeof(decimal)) .Resolve() .Methods.FirstOrDefault( md => md.IsConstructor && md.Parameters.Count == 1 && md.Parameters[0].ParameterType.FullName == "System.Int32"); var decimalctor = context.Body.Method.Module.ImportReference(decimalctorinfo); yield return(Instruction.Create(OpCodes.Newobj, decimalctor)); } } else if (implicitOperator != null) { yield return(Instruction.Create(OpCodes.Ldstr, node.Value as string)); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(implicitOperator))); } else { yield return(Instruction.Create(OpCodes.Ldnull)); } if (isNullable) { yield return(Instruction.Create(OpCodes.Newobj, module.ImportReference(nullableCtor))); } if (originalTypeRef.IsValueType && boxValueTypes) { yield return(Instruction.Create(OpCodes.Box, module.ImportReference(originalTypeRef))); } }
public SetFieldVisitor(ILContext context) { Context = context; }
public static IEnumerable <Instruction> PushParentObjectsArray(this INode node, ILContext context) { var module = context.Body.Method.Module; var nodes = new List <IElementNode>(); INode n = node.Parent; while (n != null) { var en = n as IElementNode; if (en != null && context.Variables.ContainsKey(en)) { nodes.Add(en); } n = n.Parent; } if (nodes.Count == 0 && context.ParentContextValues == null) { yield return(Instruction.Create(OpCodes.Ldnull)); yield break; } if (nodes.Count == 0) { yield return(Instruction.Create(OpCodes.Ldarg_0)); yield return(Instruction.Create(OpCodes.Ldfld, context.ParentContextValues)); yield break; } //Compute parent object length if (context.ParentContextValues != null) { yield return(Instruction.Create(OpCodes.Ldarg_0)); yield return(Instruction.Create(OpCodes.Ldfld, context.ParentContextValues)); yield return(Instruction.Create(OpCodes.Ldlen)); yield return(Instruction.Create(OpCodes.Conv_I4)); } else { yield return(Instruction.Create(OpCodes.Ldc_I4_0)); } var parentObjectLength = new VariableDefinition(module.TypeSystem.Int32); context.Body.Variables.Add(parentObjectLength); yield return(Instruction.Create(OpCodes.Stloc, parentObjectLength)); //Create the final array yield return(Instruction.Create(OpCodes.Ldloc, parentObjectLength)); yield return(Instruction.Create(OpCodes.Ldc_I4, nodes.Count)); yield return(Instruction.Create(OpCodes.Add)); yield return(Instruction.Create(OpCodes.Newarr, module.TypeSystem.Object)); var finalArray = new VariableDefinition(module.ImportReference(typeof(object[]))); context.Body.Variables.Add(finalArray); yield return(Instruction.Create(OpCodes.Stloc, finalArray)); //Copy original array to final if (context.ParentContextValues != null) { yield return(Instruction.Create(OpCodes.Ldarg_0)); yield return(Instruction.Create(OpCodes.Ldfld, context.ParentContextValues)); //sourceArray yield return(Instruction.Create(OpCodes.Ldc_I4_0)); //sourceIndex yield return(Instruction.Create(OpCodes.Ldloc, finalArray)); //destinationArray yield return(Instruction.Create(OpCodes.Ldc_I4, nodes.Count)); //destinationIndex yield return(Instruction.Create(OpCodes.Ldloc, parentObjectLength)); //length var arrayCopy = module.ImportReference(typeof(Array)) .Resolve() .Methods.First( md => md.Name == "Copy" && md.Parameters.Count == 5 && md.Parameters[1].ParameterType.FullName == module.TypeSystem.Int32.FullName); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(arrayCopy))); } //Add nodes to array yield return(Instruction.Create(OpCodes.Ldloc, finalArray)); if (nodes.Count > 0) { for (var i = 0; i < nodes.Count; i++) { var en = nodes[i]; yield return(Instruction.Create(OpCodes.Dup)); yield return(Instruction.Create(OpCodes.Ldc_I4, i)); yield return(Instruction.Create(OpCodes.Ldloc, context.Variables[en])); if (context.Variables[en].VariableType.IsValueType) { yield return(Instruction.Create(OpCodes.Box, module.ImportReference(context.Variables[en].VariableType))); } yield return(Instruction.Create(OpCodes.Stelem_Ref)); } } }
public static IEnumerable <Instruction> PushServiceProvider(this INode node, ILContext context, FieldReference bpRef = null, PropertyReference propertyRef = null, TypeReference declaringTypeReference = null) { var module = context.Body.Method.Module; #if NOSERVICEPROVIDER yield return(Instruction.Create(OpCodes.Ldnull)); yield break; #endif var ctorinfo = typeof(XamlServiceProvider).GetConstructor(new Type[] { }); var ctor = module.ImportReference(ctorinfo); var addServiceInfo = typeof(XamlServiceProvider).GetMethod("Add", new[] { typeof(Type), typeof(object) }); var addService = module.ImportReference(addServiceInfo); var getTypeFromHandle = module.ImportReference(typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) })); var getAssembly = module.ImportReference(typeof(Type).GetProperty("Assembly").GetMethod); yield return(Instruction.Create(OpCodes.Newobj, ctor)); //Add a SimpleValueTargetProvider var pushParentIl = node.PushParentObjectsArray(context).ToList(); if (pushParentIl[pushParentIl.Count - 1].OpCode != OpCodes.Ldnull) { yield return(Instruction.Create(OpCodes.Dup)); //Keep the serviceProvider on the stack yield return(Instruction.Create(OpCodes.Ldtoken, module.ImportReference(typeof(IProvideValueTarget)))); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(getTypeFromHandle))); foreach (var instruction in pushParentIl) { yield return(instruction); } foreach (var instruction in PushTargetProperty(bpRef, propertyRef, declaringTypeReference, module)) { yield return(instruction); } var targetProviderCtor = module.ImportReference(typeof(SimpleValueTargetProvider).GetConstructor(new[] { typeof(object[]), typeof(object) })); yield return(Instruction.Create(OpCodes.Newobj, targetProviderCtor)); yield return(Instruction.Create(OpCodes.Callvirt, addService)); } //Add a NamescopeProvider if (context.Scopes.ContainsKey(node)) { yield return(Instruction.Create(OpCodes.Dup)); //Dupicate the serviceProvider yield return(Instruction.Create(OpCodes.Ldtoken, module.ImportReference(typeof(INameScopeProvider)))); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(getTypeFromHandle))); var namescopeProviderCtor = module.ImportReference(typeof(NameScopeProvider).GetConstructor(new Type[] { })); yield return(Instruction.Create(OpCodes.Newobj, namescopeProviderCtor)); yield return(Instruction.Create(OpCodes.Dup)); //Duplicate the namescopeProvider var setNamescope = module.ImportReference(typeof(NameScopeProvider).GetProperty("NameScope").GetSetMethod()); yield return(Instruction.Create(OpCodes.Ldloc, context.Scopes[node].Item1)); yield return(Instruction.Create(OpCodes.Callvirt, setNamescope)); yield return(Instruction.Create(OpCodes.Callvirt, addService)); } //Add a XamlTypeResolver if (node.NamespaceResolver != null) { yield return(Instruction.Create(OpCodes.Dup)); //Dupicate the serviceProvider yield return(Instruction.Create(OpCodes.Ldtoken, module.ImportReference(typeof(IXamlTypeResolver)))); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(getTypeFromHandle))); var xmlNamespaceResolverCtor = module.ImportReference(typeof(XmlNamespaceResolver).GetConstructor(new Type[] { })); var addNamespace = module.ImportReference(typeof(XmlNamespaceResolver).GetMethod("Add")); yield return(Instruction.Create(OpCodes.Newobj, xmlNamespaceResolverCtor)); foreach (var kvp in node.NamespaceResolver.GetNamespacesInScope(XmlNamespaceScope.ExcludeXml)) { yield return(Instruction.Create(OpCodes.Dup)); //dup the resolver yield return(Instruction.Create(OpCodes.Ldstr, kvp.Key)); yield return(Instruction.Create(OpCodes.Ldstr, kvp.Value)); yield return(Instruction.Create(OpCodes.Callvirt, addNamespace)); } yield return(Instruction.Create(OpCodes.Ldtoken, context.Body.Method.DeclaringType)); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(getTypeFromHandle))); yield return(Instruction.Create(OpCodes.Callvirt, getAssembly)); var xtr = module.ImportReference(typeof(XamlTypeResolver)).Resolve(); var xamlTypeResolverCtor = module.ImportReference(xtr.Methods.First(md => md.IsConstructor && md.Parameters.Count == 2)); yield return(Instruction.Create(OpCodes.Newobj, xamlTypeResolverCtor)); yield return(Instruction.Create(OpCodes.Callvirt, addService)); } if (node is IXmlLineInfo) { yield return(Instruction.Create(OpCodes.Dup)); //Dupicate the serviceProvider yield return(Instruction.Create(OpCodes.Ldtoken, module.ImportReference(typeof(IXmlLineInfoProvider)))); yield return(Instruction.Create(OpCodes.Call, module.ImportReference(getTypeFromHandle))); foreach (var instruction in node.PushXmlLineInfo(context)) { yield return(instruction); } var lip = module.ImportReference(typeof(XmlLineInfoProvider)).Resolve(); var lineInfoProviderCtor = module.ImportReference(lip.Methods.First(md => md.IsConstructor && md.Parameters.Count == 1)); yield return(Instruction.Create(OpCodes.Newobj, lineInfoProviderCtor)); yield return(Instruction.Create(OpCodes.Callvirt, addService)); } }
static void SetDataTemplate(IElementNode parentNode, ElementNode node, ILContext parentContext, IXmlLineInfo xmlLineInfo) { var parentVar = parentContext.Variables[parentNode]; //Push the DataTemplate to the stack, for setting the template parentContext.IL.Emit(OpCodes.Ldloc, parentVar); //Create nested class // .class nested private auto ansi sealed beforefieldinit '<Main>c__AnonStorey0' // extends [mscorlib]System.Object var module = parentContext.Body.Method.Module; var anonType = new TypeDefinition( null, "<" + parentContext.Body.Method.Name + ">_anonXamlCDataTemplate_" + dtcount++, TypeAttributes.BeforeFieldInit | TypeAttributes.Sealed | TypeAttributes.NestedPrivate) { BaseType = module.TypeSystem.Object }; parentContext.Body.Method.DeclaringType.NestedTypes.Add(anonType); var ctor = anonType.AddDefaultConstructor(); var loadTemplate = new MethodDefinition("LoadDataTemplate", MethodAttributes.Assembly | MethodAttributes.HideBySig, module.TypeSystem.Object); anonType.Methods.Add(loadTemplate); var parentValues = new FieldDefinition("parentValues", FieldAttributes.Assembly, module.Import(typeof(object[]))); anonType.Fields.Add(parentValues); TypeReference rootType = null; var vdefRoot = parentContext.Root as VariableDefinition; if (vdefRoot != null) { rootType = vdefRoot.VariableType; } var fdefRoot = parentContext.Root as FieldDefinition; if (fdefRoot != null) { rootType = fdefRoot.FieldType; } var root = new FieldDefinition("root", FieldAttributes.Assembly, rootType); anonType.Fields.Add(root); //Fill the loadTemplate Body var templateIl = loadTemplate.Body.GetILProcessor(); templateIl.Emit(OpCodes.Nop); var templateContext = new ILContext(templateIl, loadTemplate.Body, parentValues) { Root = root }; node.Accept(new CreateObjectVisitor(templateContext), null); node.Accept(new SetNamescopesAndRegisterNamesVisitor(templateContext), null); node.Accept(new SetFieldVisitor(templateContext), null); node.Accept(new SetResourcesVisitor(templateContext), null); node.Accept(new SetPropertiesVisitor(templateContext), null); templateIl.Emit(OpCodes.Ldloc, templateContext.Variables[node]); templateIl.Emit(OpCodes.Ret); //Instanciate nested class var parentIl = parentContext.IL; parentIl.Emit(OpCodes.Newobj, ctor); //Copy required local vars parentIl.Emit(OpCodes.Dup); //Duplicate the nestedclass instance parentIl.Append(node.PushParentObjectsArray(parentContext)); parentIl.Emit(OpCodes.Stfld, parentValues); parentIl.Emit(OpCodes.Dup); //Duplicate the nestedclass instance if (parentContext.Root is VariableDefinition) { parentIl.Emit(OpCodes.Ldloc, parentContext.Root as VariableDefinition); } else if (parentContext.Root is FieldDefinition) { parentIl.Emit(OpCodes.Ldarg_0); parentIl.Emit(OpCodes.Ldfld, parentContext.Root as FieldDefinition); } else { throw new InvalidProgramException(); } parentIl.Emit(OpCodes.Stfld, root); //SetDataTemplate parentIl.Emit(OpCodes.Ldftn, loadTemplate); var funcObjRef = module.Import(typeof(Func <object>)); var funcCtor = funcObjRef .Resolve() .Methods.First(md => md.IsConstructor && md.Parameters.Count == 2) .ResolveGenericParameters(funcObjRef, module); parentIl.Emit(OpCodes.Newobj, module.Import(funcCtor)); #pragma warning disable 0612 var propertySetter = module.Import(typeof(IDataTemplate)).Resolve().Properties.First(p => p.Name == "LoadTemplate").SetMethod; #pragma warning restore 0612 parentContext.IL.Emit(OpCodes.Callvirt, module.Import(propertySetter)); }
public static bool CanConvertValue(this ValueNode node, ILContext context, TypeReference targetTypeRef, TypeReference typeConverter) { var str = (string)node.Value; var module = context.Body.Method.Module; //If there's a [TypeConverter], use it if (typeConverter != null && str != null) { var typeConvAttribute = typeConverter.GetCustomAttribute(module, ("Xamarin.Forms.Core", "Xamarin.Forms.Xaml", "TypeConversionAttribute")); if (typeConvAttribute == null) //trust the unattributed TypeConverter { return(true); } var toType = typeConvAttribute.ConstructorArguments.First().Value as TypeReference; return(toType.InheritsFromOrImplements(targetTypeRef)); } //check if it's assignable from a string if (targetTypeRef.ResolveCached().FullName == "System.Nullable`1") { targetTypeRef = ((GenericInstanceType)targetTypeRef).GenericArguments[0]; } if (targetTypeRef.ResolveCached().BaseType != null && targetTypeRef.ResolveCached().BaseType.FullName == "System.Enum") { return(true); } if (targetTypeRef.FullName == "System.Char") { return(true); } if (targetTypeRef.FullName == "System.SByte") { return(true); } if (targetTypeRef.FullName == "System.Int16") { return(true); } if (targetTypeRef.FullName == "System.Int32") { return(true); } if (targetTypeRef.FullName == "System.Int64") { return(true); } if (targetTypeRef.FullName == "System.Byte") { return(true); } if (targetTypeRef.FullName == "System.UInt16") { return(true); } if (targetTypeRef.FullName == "System.UInt32") { return(true); } if (targetTypeRef.FullName == "System.UInt64") { return(true); } if (targetTypeRef.FullName == "System.Single") { return(true); } if (targetTypeRef.FullName == "System.Double") { return(true); } if (targetTypeRef.FullName == "System.Boolean") { return(true); } if (targetTypeRef.FullName == "System.TimeSpan") { return(true); } if (targetTypeRef.FullName == "System.DateTime") { return(true); } if (targetTypeRef.FullName == "System.String") { return(true); } if (targetTypeRef.FullName == "System.Object") { return(true); } if (targetTypeRef.FullName == "System.Decimal") { return(true); } var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(targetTypeRef, module); if (implicitOperator != null) { return(true); } return(false); }
public static IEnumerable <Instruction> ProvideValue(VariableDefinitionReference vardefref, ILContext context, ModuleDefinition module, ElementNode node) { GenericInstanceType markupExtension; IList <TypeReference> genericArguments; if (vardefref.VariableDefinition.VariableType.FullName == "Xamarin.Forms.Xaml.ArrayExtension" && vardefref.VariableDefinition.VariableType.ImplementsGenericInterface("Xamarin.Forms.Xaml.IMarkupExtension`1", out markupExtension, out genericArguments)) { var markExt = markupExtension.Resolve(); var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue"); var provideValue = module.Import(provideValueInfo); provideValue = module.Import(provideValue.ResolveGenericParameters(markupExtension, module)); var typeNode = node.Properties[new XmlName("", "Type")]; TypeReference arrayTypeRef; if (context.TypeExtensions.TryGetValue(typeNode, out arrayTypeRef)) { vardefref.VariableDefinition = new VariableDefinition(module.Import(arrayTypeRef.MakeArrayType())); } else { vardefref.VariableDefinition = new VariableDefinition(module.Import(genericArguments.First())); } yield return(Instruction.Create(OpCodes.Ldloc, context.Variables[node])); foreach (var instruction in node.PushServiceProvider(context)) { yield return(instruction); } yield return(Instruction.Create(OpCodes.Callvirt, provideValue)); if (arrayTypeRef != null) { yield return(Instruction.Create(OpCodes.Castclass, module.Import(arrayTypeRef.MakeArrayType()))); } yield return(Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition)); } else if (vardefref.VariableDefinition.VariableType.ImplementsGenericInterface("Xamarin.Forms.Xaml.IMarkupExtension`1", out markupExtension, out genericArguments)) { var markExt = markupExtension.Resolve(); var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue"); var provideValue = module.Import(provideValueInfo); provideValue = module.Import(provideValue.ResolveGenericParameters(markupExtension, module)); vardefref.VariableDefinition = new VariableDefinition(module.Import(genericArguments.First())); yield return(Instruction.Create(OpCodes.Ldloc, context.Variables[node])); foreach (var instruction in node.PushServiceProvider(context)) { yield return(instruction); } yield return(Instruction.Create(OpCodes.Callvirt, provideValue)); yield return(Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition)); } else if (context.Variables[node].VariableType.ImplementsInterface(module.Import(typeof(IMarkupExtension)))) { var markExt = module.Import(typeof(IMarkupExtension)).Resolve(); var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue"); var provideValue = module.Import(provideValueInfo); vardefref.VariableDefinition = new VariableDefinition(module.TypeSystem.Object); yield return(Instruction.Create(OpCodes.Ldloc, context.Variables[node])); foreach (var instruction in node.PushServiceProvider(context)) { yield return(instruction); } yield return(Instruction.Create(OpCodes.Callvirt, provideValue)); yield return(Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition)); } else if (context.Variables[node].VariableType.ImplementsInterface(module.Import(typeof(IValueProvider)))) { var markExt = module.Import(typeof(IValueProvider)).Resolve(); var provideValueInfo = markExt.Methods.First(md => md.Name == "ProvideValue"); var provideValue = module.Import(provideValueInfo); vardefref.VariableDefinition = new VariableDefinition(module.TypeSystem.Object); yield return(Instruction.Create(OpCodes.Ldloc, context.Variables[node])); foreach (var instruction in node.PushServiceProvider(context)) { yield return(instruction); } yield return(Instruction.Create(OpCodes.Callvirt, provideValue)); yield return(Instruction.Create(OpCodes.Stloc, vardefref.VariableDefinition)); } }
public static void SetPropertyValue(VariableDefinition parent, XmlName propertyName, INode valueNode, ILContext context, IXmlLineInfo iXmlLineInfo) { var elementType = parent.VariableType; var localName = propertyName.LocalName; var module = context.Body.Method.Module; var br = Instruction.Create(OpCodes.Nop); TypeReference declaringTypeReference; var handled = false; //If it's an attached BP, update elementType and propertyName GetNameAndTypeRef(ref elementType, propertyName.NamespaceURI, ref localName, context, iXmlLineInfo); //If the target is an event, connect // IL_0007: ldloc.0 // IL_0008: ldarg.0 // // IL_0009: ldftn instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs) //OR, if the handler is virtual // IL_000x: ldarg.0 // IL_0009: ldvirtftn instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs) // // IL_000f: newobj instance void class [mscorlib]System.EventHandler::'.ctor'(object, native int) // IL_0014: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.Button::add_Clicked(class [mscorlib]System.EventHandler) var eventinfo = elementType.GetEvent(ed => ed.Name == localName); if (eventinfo != null) { var value = ((ValueNode)valueNode).Value; context.IL.Emit(OpCodes.Ldloc, parent); if (context.Root is VariableDefinition) { context.IL.Emit(OpCodes.Ldloc, context.Root as VariableDefinition); } else if (context.Root is FieldDefinition) { context.IL.Emit(OpCodes.Ldarg_0); context.IL.Emit(OpCodes.Ldfld, context.Root as FieldDefinition); } else { throw new InvalidProgramException(); } var declaringType = context.Body.Method.DeclaringType; if (declaringType.IsNested) { declaringType = declaringType.DeclaringType; } var handler = declaringType.AllMethods().FirstOrDefault(md => md.Name == value as string); if (handler == null) { throw new XamlParseException( string.Format("EventHandler \"{0}\" not found in type \"{1}\"", value, context.Body.Method.DeclaringType.FullName), iXmlLineInfo); } if (handler.IsVirtual) { context.IL.Emit(OpCodes.Ldarg_0); context.IL.Emit(OpCodes.Ldvirtftn, handler); } else { context.IL.Emit(OpCodes.Ldftn, handler); } //FIXME: eventually get the right ctor instead fo the First() one, just in case another one could exists (not even sure it's possible). var ctor = module.Import(eventinfo.EventType.Resolve().GetConstructors().First()); ctor = ctor.ResolveGenericParameters(eventinfo.EventType, module); context.IL.Emit(OpCodes.Newobj, module.Import(ctor)); context.IL.Emit(OpCodes.Callvirt, module.Import(eventinfo.AddMethod)); return; } FieldReference bpRef = elementType.GetField(fd => fd.Name == localName + "Property" && fd.IsStatic && fd.IsPublic, out declaringTypeReference); if (bpRef != null) { bpRef = module.Import(bpRef.ResolveGenericParameters(declaringTypeReference)); bpRef.FieldType = module.Import(bpRef.FieldType); } //If Value is DynamicResource, SetDynamicResource VariableDefinition varValue; if (bpRef != null && valueNode is IElementNode && context.Variables.TryGetValue(valueNode as IElementNode, out varValue) && varValue.VariableType.FullName == typeof(DynamicResource).FullName) { var setDynamicResource = module.Import(typeof(IDynamicResourceHandler)).Resolve().Methods.First(m => m.Name == "SetDynamicResource"); var getKey = typeof(DynamicResource).GetProperty("Key").GetMethod; context.IL.Emit(OpCodes.Ldloc, parent); context.IL.Emit(OpCodes.Ldsfld, bpRef); context.IL.Emit(OpCodes.Ldloc, varValue); context.IL.Emit(OpCodes.Callvirt, module.Import(getKey)); context.IL.Emit(OpCodes.Callvirt, module.Import(setDynamicResource)); return; } //If Value is a BindingBase and target is a BP, SetBinding if (bpRef != null && valueNode is IElementNode && context.Variables.TryGetValue(valueNode as IElementNode, out varValue) && varValue.VariableType.InheritsFromOrImplements(module.Import(typeof(BindingBase)))) { //TODO: check if parent is a BP var setBinding = typeof(BindableObject).GetMethod("SetBinding", new[] { typeof(BindableProperty), typeof(BindingBase) }); context.IL.Emit(OpCodes.Ldloc, parent); context.IL.Emit(OpCodes.Ldsfld, bpRef); context.IL.Emit(OpCodes.Ldloc, varValue); context.IL.Emit(OpCodes.Callvirt, module.Import(setBinding)); return; } //If it's a BP, SetValue () // IL_0007: ldloc.0 // IL_0008: ldsfld class [Xamarin.Forms.Core]Xamarin.Forms.BindableProperty [Xamarin.Forms.Core]Xamarin.Forms.Label::TextProperty // IL_000d: ldstr "foo" // IL_0012: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.BindableObject::SetValue(class [Xamarin.Forms.Core]Xamarin.Forms.BindableProperty, object) if (bpRef != null) { //TODO: check if parent is a BP var setValue = typeof(BindableObject).GetMethod("SetValue", new[] { typeof(BindableProperty), typeof(object) }); if (valueNode is ValueNode) { context.IL.Emit(OpCodes.Ldloc, parent); context.IL.Emit(OpCodes.Ldsfld, bpRef); context.IL.Append(((ValueNode)valueNode).PushConvertedValue(context, bpRef, valueNode.PushServiceProvider(context), true, false)); context.IL.Emit(OpCodes.Callvirt, module.Import(setValue)); return; } if (valueNode is IElementNode) { var getPropertyReturnType = module.Import(typeof(BindableProperty).GetProperty("ReturnType").GetGetMethod()); //FIXME: this should check for inheritance too var isInstanceOfType = module.Import(typeof(Type).GetMethod("IsInstanceOfType", new[] { typeof(object) })); var brfalse = Instruction.Create(OpCodes.Nop); context.IL.Emit(OpCodes.Ldsfld, bpRef); context.IL.Emit(OpCodes.Call, getPropertyReturnType); context.IL.Emit(OpCodes.Ldloc, context.Variables[valueNode as IElementNode]); if (context.Variables[valueNode as IElementNode].VariableType.IsValueType) { context.IL.Emit(OpCodes.Box, context.Variables[valueNode as IElementNode].VariableType); } context.IL.Emit(OpCodes.Callvirt, isInstanceOfType); context.IL.Emit(OpCodes.Brfalse, brfalse); context.IL.Emit(OpCodes.Ldloc, parent); context.IL.Emit(OpCodes.Ldsfld, bpRef); context.IL.Emit(OpCodes.Ldloc, context.Variables[(IElementNode)valueNode]); if (context.Variables[valueNode as IElementNode].VariableType.IsValueType) { context.IL.Emit(OpCodes.Box, context.Variables[valueNode as IElementNode].VariableType); } context.IL.Emit(OpCodes.Callvirt, module.Import(setValue)); context.IL.Emit(OpCodes.Br, br); context.IL.Append(brfalse); handled = true; } } //If it's a property, set it // IL_0007: ldloc.0 // IL_0008: ldstr "foo" // IL_000d: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.Label::set_Text(string) PropertyDefinition property = elementType.GetProperty(pd => pd.Name == localName, out declaringTypeReference); MethodDefinition propertySetter; if (property != null && (propertySetter = property.SetMethod) != null && propertySetter.IsPublic) { module.Import(elementType.Resolve()); var propertySetterRef = module.Import(module.Import(propertySetter).ResolveGenericParameters(declaringTypeReference, module)); propertySetterRef.ImportTypes(module); var propertyType = property.ResolveGenericPropertyType(declaringTypeReference); ValueNode vnode = null; if ((vnode = valueNode as ValueNode) != null) { context.IL.Emit(OpCodes.Ldloc, parent); context.IL.Append(vnode.PushConvertedValue(context, propertyType, new ICustomAttributeProvider[] { property, propertyType.Resolve() }, valueNode.PushServiceProvider(context), false, true)); context.IL.Emit(OpCodes.Callvirt, propertySetterRef); context.IL.Append(br); return; } if (valueNode is IElementNode) { var vardef = context.Variables[(ElementNode)valueNode]; var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(propertyType, module); //TODO replace latest check by a runtime type check if (implicitOperator != null || vardef.VariableType.InheritsFromOrImplements(propertyType) || propertyType.FullName == "System.Object" || vardef.VariableType.FullName == "System.Object") { context.IL.Emit(OpCodes.Ldloc, parent); context.IL.Emit(OpCodes.Ldloc, vardef); if (implicitOperator != null) { // IL_000f: call !0 class [Xamarin.Forms.Core]Xamarin.Forms.OnPlatform`1<bool>::op_Implicit(class [Xamarin.Forms.Core]Xamarin.Forms.OnPlatform`1<!0>) context.IL.Emit(OpCodes.Call, module.Import(implicitOperator)); } else if (!vardef.VariableType.IsValueType && propertyType.IsValueType) { context.IL.Emit(OpCodes.Unbox_Any, module.Import(propertyType)); } else if (vardef.VariableType.IsValueType && propertyType.FullName == "System.Object") { context.IL.Emit(OpCodes.Box, vardef.VariableType); } context.IL.Emit(OpCodes.Callvirt, propertySetterRef); context.IL.Append(br); return; } handled = true; } } //If it's an already initialized property, add to it MethodDefinition propertyGetter; //TODO: check if property is assigned if (property != null && (propertyGetter = property.GetMethod) != null && propertyGetter.IsPublic) { var propertyGetterRef = module.Import(propertyGetter); propertyGetterRef = module.Import(propertyGetterRef.ResolveGenericParameters(declaringTypeReference, module)); var propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(declaringTypeReference); var vardef = context.Variables [(ElementNode)valueNode]; //TODO check md.Parameters[0] type var adderTuple = propertyType.GetMethods(md => md.Name == "Add" && md.Parameters.Count == 1, module).FirstOrDefault(); if (adderTuple != null) { var adderRef = module.Import(adderTuple.Item1); adderRef = module.Import(adderRef.ResolveGenericParameters(adderTuple.Item2, module)); var childType = GetParameterType(adderRef.Parameters [0]); var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(childType, module); if (valueNode is IElementNode) { context.IL.Emit(OpCodes.Ldloc, parent); context.IL.Emit(OpCodes.Callvirt, propertyGetterRef); context.IL.Emit(OpCodes.Ldloc, vardef); if (implicitOperator != null) { context.IL.Emit(OpCodes.Call, module.Import(implicitOperator)); } context.IL.Emit(OpCodes.Callvirt, adderRef); if (adderRef.ReturnType.FullName != "System.Void") { context.IL.Emit(OpCodes.Pop); } context.IL.Append(br); return; } } } if (!handled) { throw new XamlParseException(string.Format("No property, bindable property, or event found for '{0}'", localName), iXmlLineInfo); } context.IL.Append(br); }
public SetPropertiesVisitor(ILContext context, bool stopOnResourceDictionary = false) { Context = context; Module = context.Body.Method.Module; StopOnResourceDictionary = stopOnResourceDictionary; }
public bool Compile() { LogLine(1, "Compiling Xaml"); LogLine(1, "\nAssembly: {0}", Assembly); if (!string.IsNullOrEmpty(DependencyPaths)) { LogLine(1, "DependencyPaths: \t{0}", DependencyPaths); } if (!string.IsNullOrEmpty(ReferencePath)) { LogLine(1, "ReferencePath: \t{0}", ReferencePath.Replace("//", "/")); } LogLine(3, "DebugSymbols:\"{0}\"", DebugSymbols); var skipassembly = true; //change this to false to enable XamlC by default bool success = true; if (!File.Exists(Assembly)) { LogLine(1, "Assembly file not found. Skipping XamlC."); return(true); } var resolver = new XamlCAssemblyResolver(); if (!string.IsNullOrEmpty(DependencyPaths)) { foreach (var dep in DependencyPaths.Split(';')) { LogLine(3, "Adding searchpath {0}", dep); resolver.AddSearchDirectory(dep); } } if (!string.IsNullOrEmpty(ReferencePath)) { var paths = ReferencePath.Replace("//", "/").Split(';'); foreach (var p in paths) { var searchpath = Path.GetDirectoryName(p); LogLine(3, "Adding searchpath {0}", searchpath); resolver.AddSearchDirectory(searchpath); // LogLine (3, "Referencing {0}", p); // resolver.AddAssembly (p); } } var assemblyDefinition = AssemblyDefinition.ReadAssembly(Path.GetFullPath(Assembly), new ReaderParameters { AssemblyResolver = resolver, ReadSymbols = DebugSymbols }); CustomAttribute xamlcAttr; if (assemblyDefinition.HasCustomAttributes && (xamlcAttr = assemblyDefinition.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipassembly = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipassembly = false; } } foreach (var module in assemblyDefinition.Modules) { var skipmodule = skipassembly; if (module.HasCustomAttributes && (xamlcAttr = module.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skipmodule = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skipmodule = false; } } LogLine(2, " Module: {0}", module.Name); var resourcesToPrune = new List <EmbeddedResource>(); foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { LogString(2, " Resource: {0}... ", resource.Name); string classname; if (!resource.IsXaml(out classname)) { LogLine(2, "skipped."); continue; } TypeDefinition typeDef = module.GetType(classname); if (typeDef == null) { LogLine(2, "no type found... skipped."); continue; } var skiptype = skipmodule; if (typeDef.HasCustomAttributes && (xamlcAttr = typeDef.CustomAttributes.FirstOrDefault( ca => ca.AttributeType.FullName == "Xamarin.Forms.Xaml.XamlCompilationAttribute")) != null) { var options = (XamlCompilationOptions)xamlcAttr.ConstructorArguments[0].Value; if ((options & XamlCompilationOptions.Skip) == XamlCompilationOptions.Skip) { skiptype = true; } if ((options & XamlCompilationOptions.Compile) == XamlCompilationOptions.Compile) { skiptype = false; } } if (skiptype) { LogLine(2, "Has XamlCompilationAttribute set to Skip and not Compile... skipped"); continue; } var initComp = typeDef.Methods.FirstOrDefault(md => md.Name == "InitializeComponent"); if (initComp == null) { LogLine(2, "no InitializeComponent found... skipped."); continue; } LogLine(2, ""); LogString(2, " Parsing Xaml... "); var rootnode = ParseXaml(resource.GetResourceStream(), typeDef); if (rootnode == null) { LogLine(2, "failed."); continue; } LogLine(2, "done."); hasCompiledXamlResources = true; try { LogString(2, " Replacing {0}.InitializeComponent ()... ", typeDef.Name); var body = new MethodBody(initComp); var il = body.GetILProcessor(); il.Emit(OpCodes.Nop); var visitorContext = new ILContext(il, body); rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null); rootnode.Accept(new CreateObjectVisitor(visitorContext), null); rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null); rootnode.Accept(new SetFieldVisitor(visitorContext), null); rootnode.Accept(new SetResourcesVisitor(visitorContext), null); rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null); il.Emit(OpCodes.Ret); initComp.Body = body; } catch (XamlParseException xpe) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, xpe.XmlInfo.LineNumber, xpe.XmlInfo.LinePosition, 0, 0, xpe.Message, xpe.HelpLink, xpe.Source); LogLine(4, xpe.StackTrace); success = false; continue; } catch (XmlException xe) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, xe.LineNumber, xe.LinePosition, 0, 0, xe.Message, xe.HelpLink, xe.Source); LogLine(4, xe.StackTrace); success = false; continue; } catch (Exception e) { LogLine(2, "failed."); LogError(null, null, null, resource.Name, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); LogLine(4, e.StackTrace); success = false; continue; } LogLine(2, "done."); if (OptimizeIL) { LogString(2, " Optimizing IL... "); initComp.Body.OptimizeMacros(); LogLine(2, "done"); } if (OutputGeneratedILAsCode) { var filepath = Path.Combine(Path.GetDirectoryName(Assembly), typeDef.FullName + ".decompiled.cs"); LogString(2, " Decompiling {0} into {1}...", typeDef.FullName, filepath); var decompilerContext = new DecompilerContext(module); using (var writer = new StreamWriter(filepath)) { var output = new PlainTextOutput(writer); var codeDomBuilder = new AstBuilder(decompilerContext); codeDomBuilder.AddType(typeDef); codeDomBuilder.GenerateCode(output); } LogLine(2, "done"); } resourcesToPrune.Add(resource); } if (!KeepXamlResources) { if (resourcesToPrune.Any()) { LogLine(2, " Removing compiled xaml resources"); } foreach (var resource in resourcesToPrune) { LogString(2, " Removing {0}... ", resource.Name); module.Resources.Remove(resource); LogLine(2, "done"); } } LogLine(2, ""); } if (!hasCompiledXamlResources) { LogLine(1, "No compiled resources. Skipping writing assembly."); return(success); } LogString(1, "Writing the assembly... "); try { assemblyDefinition.Write(Assembly, new WriterParameters { WriteSymbols = DebugSymbols }); LogLine(1, "done."); } catch (Exception e) { LogLine(1, "failed."); LogError(null, null, null, null, 0, 0, 0, 0, e.Message, e.HelpLink, e.Source); LogLine(4, e.StackTrace); success = false; } return(success); }
public static bool MatchXArguments(this MethodDefinition methodDef, ElementNode enode, TypeReference declaringTypeRef, ModuleDefinition module, ILContext context) { if (!enode.Properties.ContainsKey(XmlName.xArguments)) { return(!methodDef.HasParameters); } var arguments = new List <INode>(); var node = enode.Properties[XmlName.xArguments] as ElementNode; if (node != null) { arguments.Add(node); } var list = enode.Properties[XmlName.xArguments] as ListNode; if (list != null) { foreach (var n in list.CollectionItems) { arguments.Add(n); } } if (methodDef.Parameters.Count != arguments.Count) { return(false); } for (var i = 0; i < methodDef.Parameters.Count; i++) { var paramType = methodDef.Parameters[i].ParameterType; var genParam = paramType as GenericParameter; if (genParam != null) { var index = genParam.DeclaringType.GenericParameters.IndexOf(genParam); paramType = (declaringTypeRef as GenericInstanceType).GenericArguments[index]; } var argType = context.Variables [arguments [i] as IElementNode].VariableType; if (!argType.InheritsFromOrImplements(paramType)) { return(false); } } return(true); }
public SetResourcesVisitor(ILContext context) { Context = context; Module = context.Body.Method.Module; }
public SetNamescopesAndRegisterNamesVisitor(ILContext context) { Context = context; }
public static IEnumerable <Instruction> PushConvertedValue(this ValueNode node, ILContext context, TypeReference targetTypeRef, TypeReference typeConverter, IEnumerable <Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; var str = (string)node.Value; //If the TypeConverter has a ProvideCompiledAttribute that can be resolved, shortcut this Type compiledConverterType; if (typeConverter?.GetCustomAttribute(module, ("Xamarin.Forms.Core", "Xamarin.Forms.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?.First().Value is string compiledConverterName && (compiledConverterType = Type.GetType(compiledConverterName)) != null) { var compiledConverter = Activator.CreateInstance(compiledConverterType); var converter = typeof(ICompiledTypeConverter).GetMethods().FirstOrDefault(md => md.Name == "ConvertFromString"); IEnumerable <Instruction> instructions; try { instructions = (IEnumerable <Instruction>)converter.Invoke(compiledConverter, new object[] { node.Value as string, context, node as BaseNode }); } catch (System.Reflection.TargetInvocationException tie) when(tie.InnerException is XamlParseException) { throw tie.InnerException; } catch (System.Reflection.TargetInvocationException tie) when(tie.InnerException is BuildException) { throw tie.InnerException; } foreach (var i in instructions) { yield return(i); } if (targetTypeRef.IsValueType && boxValueTypes) { yield return(Instruction.Create(OpCodes.Box, module.ImportReference(targetTypeRef))); } yield break; } //If there's a [TypeConverter], use it if (typeConverter != null) { var isExtendedConverter = typeConverter.ImplementsInterface(module.ImportReference(("Xamarin.Forms.Core", "Xamarin.Forms", "IExtendedTypeConverter"))); var typeConverterCtorRef = module.ImportCtorReference(typeConverter, paramCount: 0); var convertFromInvariantStringDefinition = isExtendedConverter ? module.ImportReference(("Xamarin.Forms.Core", "Xamarin.Forms", "IExtendedTypeConverter")) .ResolveCached() .Methods.FirstOrDefault(md => md.Name == "ConvertFromInvariantString" && md.Parameters.Count == 2) : typeConverter.ResolveCached() .AllMethods() .FirstOrDefault(md => md.methodDef.Name == "ConvertFromInvariantString" && md.methodDef.Parameters.Count == 1).methodDef; var convertFromInvariantStringReference = module.ImportReference(convertFromInvariantStringDefinition); yield return(Create(Newobj, typeConverterCtorRef)); yield return(Create(Ldstr, node.Value as string)); if (isExtendedConverter) { foreach (var instruction in pushServiceProvider) { yield return(instruction); } } yield return(Instruction.Create(OpCodes.Callvirt, convertFromInvariantStringReference)); if (targetTypeRef.IsValueType && unboxValueTypes) { yield return(Instruction.Create(OpCodes.Unbox_Any, module.ImportReference(targetTypeRef))); } //ConvertFrom returns an object, no need to Box yield break; } var originalTypeRef = targetTypeRef; var isNullable = false; MethodReference nullableCtor = null; if (targetTypeRef.ResolveCached().FullName == "System.Nullable`1") { var nullableTypeRef = targetTypeRef; targetTypeRef = ((GenericInstanceType)targetTypeRef).GenericArguments[0]; isNullable = true; nullableCtor = originalTypeRef.GetMethods(md => md.IsConstructor && md.Parameters.Count == 1, module).Single().Item1; nullableCtor = nullableCtor.ResolveGenericParameters(nullableTypeRef, module); } var implicitOperator = module.TypeSystem.String.GetImplicitOperatorTo(targetTypeRef, module); //Obvious Built-in conversions if (targetTypeRef.ResolveCached().BaseType != null && targetTypeRef.ResolveCached().BaseType.FullName == "System.Enum") { yield return(PushParsedEnum(targetTypeRef, str, node)); } else if (targetTypeRef.FullName == "System.Char") { yield return(Instruction.Create(OpCodes.Ldc_I4, unchecked ((int)Char.Parse(str)))); } else if (targetTypeRef.FullName == "System.SByte") { yield return(Instruction.Create(OpCodes.Ldc_I4, unchecked ((int)SByte.Parse(str, CultureInfo.InvariantCulture)))); } else if (targetTypeRef.FullName == "System.Int16") { yield return(Instruction.Create(OpCodes.Ldc_I4, unchecked ((int)Int16.Parse(str, CultureInfo.InvariantCulture)))); } else if (targetTypeRef.FullName == "System.Int32") { yield return(Instruction.Create(OpCodes.Ldc_I4, Int32.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Int64") { yield return(Instruction.Create(OpCodes.Ldc_I8, Int64.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Byte") { yield return(Instruction.Create(OpCodes.Ldc_I4, unchecked ((int)Byte.Parse(str, CultureInfo.InvariantCulture)))); } else if (targetTypeRef.FullName == "System.UInt16") { yield return(Instruction.Create(OpCodes.Ldc_I4, unchecked ((int)UInt16.Parse(str, CultureInfo.InvariantCulture)))); } else if (targetTypeRef.FullName == "System.UInt32") { yield return(Instruction.Create(OpCodes.Ldc_I4, unchecked ((int)UInt32.Parse(str, CultureInfo.InvariantCulture)))); } else if (targetTypeRef.FullName == "System.UInt64") { yield return(Instruction.Create(OpCodes.Ldc_I8, unchecked ((long)UInt64.Parse(str, CultureInfo.InvariantCulture)))); } else if (targetTypeRef.FullName == "System.Single") { yield return(Instruction.Create(OpCodes.Ldc_R4, Single.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Double") { yield return(Instruction.Create(OpCodes.Ldc_R8, Double.Parse(str, CultureInfo.InvariantCulture))); } else if (targetTypeRef.FullName == "System.Boolean") { if (Boolean.Parse(str)) { yield return(Instruction.Create(OpCodes.Ldc_I4_1)); } else { yield return(Instruction.Create(OpCodes.Ldc_I4_0)); } } else if (targetTypeRef.FullName == "System.TimeSpan") { var ts = TimeSpan.Parse(str, CultureInfo.InvariantCulture); var ticks = ts.Ticks; yield return(Instruction.Create(OpCodes.Ldc_I8, ticks)); yield return(Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("mscorlib", "System", "TimeSpan"), parameterTypes: new[] { ("mscorlib", "System", "Int64") })));
public CreateObjectVisitor(ILContext context) { Context = context; Module = context.Body.Method.Module; }
public IEnumerable <Instruction> ProvideValue(IElementNode node, ModuleDefinition module, ILContext context, out TypeReference memberRef) { INode ntype; if (!node.Properties.TryGetValue(new XmlName("", "Member"), out ntype)) { ntype = node.CollectionItems[0]; } var member = ((ValueNode)ntype).Value as string; if (IsNullOrEmpty(member) || !member.Contains(".")) { var lineInfo = node as IXmlLineInfo; throw new XamlParseException("Syntax for x:Static is [Member=][prefix:]typeName.staticMemberName", lineInfo); } var dotIdx = member.LastIndexOf('.'); var typename = member.Substring(0, dotIdx); var membername = member.Substring(dotIdx + 1); var typeRef = module.Import(GetTypeReference(typename, module, node)); var fieldRef = GetFieldReference(typeRef, membername, module); var propertyDef = GetPropertyDefinition(typeRef, membername, module); if (fieldRef == null && propertyDef == null) { throw new XamlParseException($"x:Static: unable to find a public static field, static property, const or enum value named {membername} in {typename}", node as IXmlLineInfo); } var fieldDef = fieldRef?.Resolve(); if (fieldRef != null) { memberRef = fieldRef.FieldType; if (!fieldDef.HasConstant) { return new [] { Instruction.Create(OpCodes.Ldsfld, fieldRef) } } ; //Constants can be numbers, Boolean values, strings, or a null reference. (https://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx) if (memberRef == module.TypeSystem.Boolean) { return new [] { Instruction.Create(((bool)fieldDef.Constant) ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0) } } ; if (memberRef == module.TypeSystem.String) { return new [] { Instruction.Create(OpCodes.Ldstr, (string)fieldDef.Constant) } } ; if (fieldDef.Constant == null) { return new [] { Instruction.Create(OpCodes.Ldnull) } } ; if (memberRef == module.TypeSystem.Char) { return new [] { Instruction.Create(OpCodes.Ldc_I4, (char)fieldDef.Constant) } } ; if (memberRef == module.TypeSystem.Single) { return new [] { Instruction.Create(OpCodes.Ldc_R4, (float)fieldDef.Constant) } } ; if (memberRef == module.TypeSystem.Double) { return new [] { Instruction.Create(OpCodes.Ldc_R8, (double)fieldDef.Constant) } } ; if (memberRef == module.TypeSystem.Byte || memberRef == module.TypeSystem.Int16 || memberRef == module.TypeSystem.Int32) { return new [] { Instruction.Create(OpCodes.Ldc_I4, (int)fieldDef.Constant) } } ; if (memberRef == module.TypeSystem.SByte || memberRef == module.TypeSystem.UInt16 || memberRef == module.TypeSystem.UInt32) { return new [] { Instruction.Create(OpCodes.Ldc_I4, (uint)fieldDef.Constant) } } ; if (memberRef == module.TypeSystem.Int64) { return new [] { Instruction.Create(OpCodes.Ldc_I8, (long)fieldDef.Constant) } } ; if (memberRef == module.TypeSystem.UInt64) { return new [] { Instruction.Create(OpCodes.Ldc_I8, (ulong)fieldDef.Constant) } } ; //enum values if (memberRef.Resolve().IsEnum) { if (fieldDef.Constant is long) { return new [] { Instruction.Create(OpCodes.Ldc_I8, (long)fieldDef.Constant) } } ; if (fieldDef.Constant is ulong) { return new [] { Instruction.Create(OpCodes.Ldc_I8, (ulong)fieldDef.Constant) } } ; if (fieldDef.Constant is uint) { return new [] { Instruction.Create(OpCodes.Ldc_I4, (uint)fieldDef.Constant) } } ; //everything else will cast just fine to an int return(new [] { Instruction.Create(OpCodes.Ldc_I4, (int)fieldDef.Constant) }); } } memberRef = propertyDef.PropertyType; var getterDef = module.Import(propertyDef.GetMethod); return(new [] { Instruction.Create(OpCodes.Call, getterDef) }); }
bool TryCoreCompile(MethodDefinition initComp, MethodDefinition initCompRuntime, ILRootNode rootnode, out Exception exception) { try { var body = new MethodBody(initComp); var module = body.Method.Module; body.InitLocals = true; var il = body.GetILProcessor(); var resourcePath = GetPathForType(module, initComp.DeclaringType); il.Emit(Nop); if (initCompRuntime != null) { // Generating branching code for the Previewer //First using the ResourceLoader var nop = Instruction.Create(Nop); var getResourceProvider = module.ImportReference(module.ImportReference(typeof(Internals.ResourceLoader)) .Resolve() .Properties.FirstOrDefault(pd => pd.Name == "ResourceProvider") .GetMethod); il.Emit(Call, getResourceProvider); il.Emit(Brfalse, nop); il.Emit(Call, getResourceProvider); var getTypeFromHandle = module.ImportReference(typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) })); var getTypeInfo = module.ImportReference(typeof(System.Reflection.IntrospectionExtensions).GetMethod("GetTypeInfo", new Type[] { typeof(Type) })); var getAssembly = module.ImportReference(typeof(Type).GetProperty("Assembly").GetMethod); var getAssemblyName = module.ImportReference(typeof(System.Reflection.Assembly).GetMethod("GetName", new Type[] { })); il.Emit(Ldtoken, module.ImportReference(initComp.DeclaringType)); il.Emit(Call, module.ImportReference(getTypeFromHandle)); il.Emit(Call, module.ImportReference(getTypeInfo)); il.Emit(Callvirt, module.ImportReference(getAssembly)); il.Emit(Callvirt, module.ImportReference(getAssemblyName)); //assemblyName il.Emit(Ldstr, resourcePath); //resourcePath var func = module.ImportReference(module.ImportReference(typeof(Func <System.Reflection.AssemblyName, string, string>)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "Invoke")); func = func.ResolveGenericParameters(module.ImportReference(typeof(Func <System.Reflection.AssemblyName, string, string>)), module); il.Emit(Callvirt, func); il.Emit(Brfalse, nop); il.Emit(Ldarg_0); il.Emit(Call, initCompRuntime); il.Emit(Ret); il.Append(nop); //Or using the deprecated XamlLoader nop = Instruction.Create(Nop); #pragma warning disable 0618 var getXamlFileProvider = module.ImportReference(module.ImportReference(typeof(Xaml.Internals.XamlLoader)) .Resolve() .Properties.FirstOrDefault(pd => pd.Name == "XamlFileProvider") .GetMethod); #pragma warning restore 0618 il.Emit(Call, getXamlFileProvider); il.Emit(Brfalse, nop); il.Emit(Call, getXamlFileProvider); il.Emit(Ldarg_0); var getType = module.ImportReference(module.ImportReference(typeof(object)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "GetType")); il.Emit(Call, getType); func = module.ImportReference(module.ImportReference(typeof(Func <Type, string>)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "Invoke")); func = func.ResolveGenericParameters(module.ImportReference(typeof(Func <Type, string>)), module); il.Emit(Callvirt, func); il.Emit(Brfalse, nop); il.Emit(Ldarg_0); il.Emit(Call, initCompRuntime); il.Emit(Ret); il.Append(nop); } var visitorContext = new ILContext(il, body, module); rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null); rootnode.Accept(new PruneIgnoredNodesVisitor(), null); rootnode.Accept(new CreateObjectVisitor(visitorContext), null); rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null); rootnode.Accept(new SetFieldVisitor(visitorContext), null); rootnode.Accept(new SetResourcesVisitor(visitorContext), null); rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null); il.Emit(Ret); initComp.Body = body; exception = null; return(true); } catch (Exception e) { exception = e; return(false); } }
public static IEnumerable <Instruction> PushConvertedValue(this ValueNode node, ILContext context, TypeReference targetTypeRef, IEnumerable <ICustomAttributeProvider> attributeProviders, IEnumerable <Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { TypeReference typeConverter = null; foreach (var attributeProvider in attributeProviders) { CustomAttribute typeConverterAttribute; if ( (typeConverterAttribute = attributeProvider.CustomAttributes.FirstOrDefault( cad => TypeConverterAttribute.TypeConvertersType.Contains(cad.AttributeType.FullName))) != null) { typeConverter = typeConverterAttribute.ConstructorArguments[0].Value as TypeReference; break; } } return(node.PushConvertedValue(context, targetTypeRef, typeConverter, pushServiceProvider, boxValueTypes, unboxValueTypes)); }
public IEnumerable <Instruction> ProvideValue(IElementNode node, ModuleDefinition module, ILContext context, out TypeReference typeRef) { typeRef = module.ImportReference(("Xamarin.Forms.Core", "Xamarin.Forms", "DataTemplate")); var name = new XmlName("", "TypeName"); if (!node.Properties.TryGetValue(name, out INode typeNameNode) && node.CollectionItems.Any()) { typeNameNode = node.CollectionItems[0]; } if (!(typeNameNode is ValueNode valueNode)) { throw new BuildException(BuildExceptionCode.PropertyMissing, node as IXmlLineInfo, null, "TypeName", typeof(Xamarin.Forms.Xaml.DataTemplateExtension)); } var contentTypeRef = module.ImportReference(XmlTypeExtensions.GetTypeReference(valueNode.Value as string, module, node as BaseNode)) ?? throw new BuildException(BuildExceptionCode.TypeResolution, node as IXmlLineInfo, null, valueNode.Value); var dataTemplateCtor = module.ImportCtorReference(typeRef, new[] { module.ImportReference(("mscorlib", "System", "Type")) });
public static IEnumerable <Instruction> PushConvertedValue(this ValueNode node, ILContext context, FieldReference bpRef, IEnumerable <Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; var targetTypeRef = bpRef.GetBindablePropertyType(node, module); var typeConverter = bpRef.GetBindablePropertyTypeConverter(module); return(node.PushConvertedValue(context, targetTypeRef, typeConverter, pushServiceProvider, boxValueTypes, unboxValueTypes)); }
public IEnumerable <Instruction> ProvideValue(IElementNode node, ModuleDefinition module, ILContext context, out TypeReference memberRef) { memberRef = module.ImportReference(typeof(Type)); INode typeNameNode; var name = new XmlName("", "TypeName"); if (!node.Properties.TryGetValue(name, out typeNameNode) && node.CollectionItems.Any()) { typeNameNode = node.CollectionItems[0]; } var valueNode = typeNameNode as ValueNode; if (valueNode == null) { throw new XamlParseException("TypeName isn't set.", node as XmlLineInfo); } if (!node.Properties.ContainsKey(name)) { node.Properties[name] = typeNameNode; node.CollectionItems.Clear(); } var typeref = module.ImportReference(XmlTypeExtensions.GetTypeReference(valueNode.Value as string, module, node as BaseNode)); if (typeref == null) { throw new XamlParseException($"Can't resolve type `{valueNode.Value}'.", node as IXmlLineInfo); } context.TypeExtensions[node] = typeref; var getTypeFromHandle = module.ImportReference(typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) })); return(new List <Instruction> { Instruction.Create(OpCodes.Ldtoken, module.ImportReference(typeref)), Instruction.Create(OpCodes.Call, module.ImportReference(getTypeFromHandle)) }); }
public ExpandMarkupsVisitor(ILContext context) => Context = context;
public ILContextProvider(ILContext context) { Context = context; }
bool TryCoreCompile(MethodDefinition initComp, MethodDefinition initCompRuntime, ILRootNode rootnode, out Exception exception) { try { var body = new MethodBody(initComp); var il = body.GetILProcessor(); il.Emit(OpCodes.Nop); if (initCompRuntime != null) { // Generating branching code for the Previewer // IL_0007: call class [mscorlib]System.Func`2<class [mscorlib]System.Type,string> class [Xamarin.Forms.Xaml.Internals]Xamarin.Forms.Xaml.XamlLoader::get_XamlFileProvider() // IL_000c: brfalse IL_0031 // IL_0011: call class [mscorlib]System.Func`2<class [mscorlib]System.Type,string> class [Xamarin.Forms.Xaml.Internals]Xamarin.Forms.Xaml.XamlLoader::get_XamlFileProvider() // IL_0016: ldarg.0 // IL_0017: call instance class [mscorlib]System.Type object::GetType() // IL_001c: callvirt instance !1 class [mscorlib]System.Func`2<class [mscorlib]System.Type, string>::Invoke(!0) // IL_0021: brfalse IL_0031 // IL_0026: ldarg.0 // IL_0027: call instance void class Xamarin.Forms.Xaml.UnitTests.XamlLoaderGetXamlForTypeTests::__InitComponentRuntime() // IL_002c: ret // IL_0031: nop var nop = Instruction.Create(OpCodes.Nop); var getXamlFileProvider = body.Method.Module.Import(body.Method.Module.Import(typeof(Xamarin.Forms.Xaml.Internals.XamlLoader)) .Resolve() .Properties.FirstOrDefault(pd => pd.Name == "XamlFileProvider") .GetMethod); il.Emit(OpCodes.Call, getXamlFileProvider); il.Emit(OpCodes.Brfalse, nop); il.Emit(OpCodes.Call, getXamlFileProvider); il.Emit(OpCodes.Ldarg_0); var getType = body.Method.Module.Import(body.Method.Module.Import(typeof(object)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "GetType")); il.Emit(OpCodes.Call, getType); var func = body.Method.Module.Import(body.Method.Module.Import(typeof(Func <Type, string>)) .Resolve() .Methods.FirstOrDefault(md => md.Name == "Invoke")); func = func.ResolveGenericParameters(body.Method.Module.Import(typeof(Func <Type, string>)), body.Method.Module); il.Emit(OpCodes.Callvirt, func); il.Emit(OpCodes.Brfalse, nop); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, initCompRuntime); il.Emit(OpCodes.Ret); il.Append(nop); } var visitorContext = new ILContext(il, body, body.Method.Module); rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null); rootnode.Accept(new PruneIgnoredNodesVisitor(), null); rootnode.Accept(new CreateObjectVisitor(visitorContext), null); rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null); rootnode.Accept(new SetFieldVisitor(visitorContext), null); rootnode.Accept(new SetResourcesVisitor(visitorContext), null); rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null); il.Emit(OpCodes.Ret); initComp.Body = body; exception = null; return(true); } catch (Exception e) { exception = e; return(false); } }
public static IEnumerable <Instruction> PushConvertedValue(this ValueNode node, ILContext context, FieldReference bpRef, IEnumerable <Instruction> pushServiceProvider, bool boxValueTypes, bool unboxValueTypes) { var module = context.Body.Method.Module; var targetTypeRef = GetBPReturnType(context, bpRef, node); TypeReference typeConverter; bpRef.HasTypeConverter(module, out typeConverter); return(node.PushConvertedValue(context, targetTypeRef, typeConverter, pushServiceProvider, boxValueTypes, unboxValueTypes)); }