Exemple #1
0
        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)));
            }
        }
Exemple #2
0
        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);
        }
Exemple #3
0
        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;
 }
Exemple #5
0
        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));
                }
            }
        }
Exemple #6
0
        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));
            }
        }
Exemple #7
0
        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);
        }
Exemple #9
0
        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));
            }
        }
Exemple #10
0
        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);
        }
Exemple #11
0
 public SetPropertiesVisitor(ILContext context, bool stopOnResourceDictionary = false)
 {
     Context = context;
     Module  = context.Body.Method.Module;
     StopOnResourceDictionary = stopOnResourceDictionary;
 }
Exemple #12
0
        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);
        }
Exemple #14
0
 public SetResourcesVisitor(ILContext context)
 {
     Context = context;
     Module  = context.Body.Method.Module;
 }
Exemple #15
0
 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") })));
Exemple #17
0
 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) });
        }
Exemple #19
0
        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);
            }
        }
Exemple #20
0
        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")) });
Exemple #22
0
        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));
        }
Exemple #23
0
        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))
            });
        }
Exemple #24
0
 public ExpandMarkupsVisitor(ILContext context) => Context = context;
 public ILContextProvider(ILContext context)
 {
     Context = context;
 }
Exemple #26
0
        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);
            }
        }
Exemple #27
0
        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));
        }