public AvaloniaXamlIlCompiler(TransformerConfiguration configuration,
                               XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings,
                               IXamlTypeBuilder <IXamlILEmitter> contextTypeBuilder)
     : this(configuration, emitMappings)
 {
     _contextType = CreateContextType(contextTypeBuilder);
 }
Beispiel #2
0
 public XamlCompiler(TransformerConfiguration configuration,
                     XamlLanguageEmitMappings <TBackendEmitter, TEmitResult> emitMappings,
                     bool fillWithDefaults)
 {
     _configuration = configuration;
     _emitMappings  = emitMappings;
     if (fillWithDefaults)
     {
         Transformers = new List <IXamlAstTransformer>
         {
             new KnownDirectivesTransformer(),
             new XamlIntrinsicsTransformer(),
             new XArgumentsTransformer(),
             new TypeReferenceResolver(),
             new MarkupExtensionTransformer(),
             new PropertyReferenceResolver(),
             new ContentConvertTransformer(),
             new ResolveContentPropertyTransformer(),
             new ResolvePropertyValueAddersTransformer(),
             new ConvertPropertyValuesToAssignmentsTransformer(),
             new ConstructableObjectTransformer()
         };
         SimplificationTransformers = new List <IXamlAstTransformer>
         {
             new FlattenAstTransformer()
         };
     }
 }
Beispiel #3
0
        public RuntimeContext(IXamlType definition, IXamlType constructedType,
                              XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> mappings,
                              string baseUri, List <IXamlField> staticProviders)
            : base(definition, constructedType, mappings,
                   (context, codegen) =>
        {
            if (staticProviders?.Count > 0)
            {
                var so = codegen.TypeSystem.GetType("System.Object");
                codegen.Ldc_I4(staticProviders.Count)
                .Newarr(so);
                for (var c = 0; c < staticProviders.Count; c++)
                {
                    codegen
                    .Dup()
                    .Ldc_I4(c)
                    .Ldsfld(staticProviders[c])
                    .Castclass(so)
                    .Stelem_ref();
                }
            }
            else
            {
                codegen.Ldnull();
            }

            codegen.Ldstr(baseUri)
            .Newobj(context.Constructor);
        })
        {
        }
 public XamlCompiler(TransformerConfiguration configuration,
                     XamlLanguageEmitMappings <TBackendEmitter, TEmitResult> emitMappings,
                     bool fillWithDefaults)
 {
     _configuration = configuration;
     _emitMappings  = emitMappings;
     if (fillWithDefaults)
     {
         Transformers = new List <IXamlAstTransformer>
         {
             new KnownDirectivesTransformer(),
             new XamlIntrinsicsTransformer(),
             new XArgumentsTransformer(),
             new TypeReferenceResolver(),
             new MarkupExtensionTransformer(),
             new TextNodeMerger(),
             new PropertyReferenceResolver(),
             new ContentConvertTransformer(),
             // This should come before actual content property processing
             new RemoveWhitespaceBetweenPropertyValuesTransformer(),
             new ResolveContentPropertyTransformer(),
             new ResolvePropertyValueAddersTransformer(),
             new ApplyWhitespaceNormalization(),
             new ConvertPropertyValuesToAssignmentsTransformer(),
             new ConstructableObjectTransformer()
         };
         SimplificationTransformers = new List <IXamlAstTransformer>
         {
             new FlattenAstTransformer()
         };
     }
 }
        public static (XamlLanguageTypeMappings language, XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emit) Configure(IXamlTypeSystem typeSystem)
        {
            var runtimeHelpers         = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
            var assignBindingAttribute = typeSystem.GetType("Avalonia.Data.AssignBindingAttribute");
            var bindingType            = typeSystem.GetType("Avalonia.Data.IBinding");
            var rv = new XamlLanguageTypeMappings(typeSystem)
            {
                SupportInitialize = typeSystem.GetType("System.ComponentModel.ISupportInitialize"),
                XmlnsAttributes   =
                {
                    typeSystem.GetType("Avalonia.Metadata.XmlnsDefinitionAttribute"),
                },
                ContentAttributes =
                {
                    typeSystem.GetType("Avalonia.Metadata.ContentAttribute")
                },
                WhitespaceSignificantCollectionAttributes =
                {
                    typeSystem.GetType("Avalonia.Metadata.WhitespaceSignificantCollectionAttribute")
                },
                TrimSurroundingWhitespaceAttributes =
                {
                    typeSystem.GetType("Avalonia.Metadata.TrimSurroundingWhitespaceAttribute")
                },
                ProvideValueTarget = typeSystem.GetType("Avalonia.Markup.Xaml.IProvideValueTarget"),
                RootObjectProvider = typeSystem.GetType("Avalonia.Markup.Xaml.IRootObjectProvider"),
                RootObjectProviderIntermediateRootPropertyName = "IntermediateRootObject",
                UriContextProvider  = typeSystem.GetType("Avalonia.Markup.Xaml.IUriContext"),
                ParentStackProvider =
                    typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlParentStackProvider"),

                XmlNamespaceInfoProvider =
                    typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.IAvaloniaXamlIlXmlNamespaceInfoProvider"),
                DeferredContentPropertyAttributes = { typeSystem.GetType("Avalonia.Metadata.TemplateContentAttribute") },
                DeferredContentExecutorCustomizationDefaultTypeParameter = typeSystem.GetType("Avalonia.Controls.IControl"),
                DeferredContentExecutorCustomizationTypeParameterDeferredContentAttributePropertyNames = new List <string>
                {
                    "TemplateResultType"
                },
                DeferredContentExecutorCustomization =
                    runtimeHelpers.FindMethod(m => m.Name == "DeferredTransformationFactoryV2"),
                UsableDuringInitializationAttributes =
                {
                    typeSystem.GetType("Avalonia.Metadata.UsableDuringInitializationAttribute"),
                },
                InnerServiceProviderFactoryMethod =
                    runtimeHelpers.FindMethod(m => m.Name == "CreateInnerServiceProviderV1"),
            };

            rv.CustomAttributeResolver = new AttributeResolver(typeSystem, rv);

            var emit = new XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult>
            {
                ProvideValueTargetPropertyEmitter = XamlIlAvaloniaPropertyHelper.EmitProvideValueTarget,
                ContextTypeBuilderCallback        = (b, c) => EmitNameScopeField(rv, typeSystem, b, c)
            };

            return(rv, emit);
        }
        public RobustXamlILCompiler(TransformerConfiguration configuration, XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings, bool fillWithDefaults) : base(configuration, emitMappings, fillWithDefaults)
        {
            Transformers.Add(new AddNameScopeRegistration());
            Transformers.Add(new RobustMarkRootObjectScopeNode());

            Emitters.Add(new AddNameScopeRegistration.Emitter());
            Emitters.Add(new RobustMarkRootObjectScopeNode.Emitter());
        }
        public WinUIXamlILCompiler(TransformerConfiguration configuration, XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings) : base(configuration, emitMappings, true)
        {
            this.AddWinUIPhases();

            Emitters.Add(new XamlDirectConversionEmitter());
            Emitters.Add(new XamlDirectNewObjectEmitter());
            Emitters.Add(new XamlDirectSetterEmitter());
            Emitters.Add(new XamlDirectAdderSetterEmitter());
            Emitters.Add(new XamlDirectEventSetterEmitter());
        }
Beispiel #8
0
 public ILEmitContext(IXamlILEmitter emitter, TransformerConfiguration configuration,
                      XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings,
                      XamlRuntimeContext <IXamlILEmitter, XamlILNodeEmitResult> runtimeContext,
                      IXamlLocal contextLocal,
                      Func <string, IXamlType, IXamlTypeBuilder <IXamlILEmitter> > createSubType, IFileSource file, IEnumerable <object> emitters)
     : base(emitter, configuration, emitMappings, runtimeContext,
            contextLocal, createSubType, file, emitters)
 {
     EnableIlVerification = configuration.GetOrCreateExtra <ILEmitContextSettings>().EnableILVerification;
 }
        private AvaloniaXamlIlCompiler(TransformerConfiguration configuration, XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings)
            : base(configuration, emitMappings, true)
        {
            _configuration = configuration;

            void InsertAfter <T>(params IXamlAstTransformer[] t)
            => Transformers.InsertRange(Transformers.FindIndex(x => x is T) + 1, t);

            void InsertBefore <T>(params IXamlAstTransformer[] t)
            => Transformers.InsertRange(Transformers.FindIndex(x => x is T), t);


            // Before everything else

            Transformers.Insert(0, new XNameTransformer());
            Transformers.Insert(1, new IgnoredDirectivesTransformer());
            Transformers.Insert(2, _designTransformer  = new AvaloniaXamlIlDesignPropertiesTransformer());
            Transformers.Insert(3, _bindingTransformer = new AvaloniaBindingExtensionTransformer());


            // Targeted
            InsertBefore <PropertyReferenceResolver>(
                new AvaloniaXamlIlResolveClassesPropertiesTransformer(),
                new AvaloniaXamlIlTransformInstanceAttachedProperties(),
                new AvaloniaXamlIlTransformSyntheticCompiledBindingMembers());
            InsertAfter <PropertyReferenceResolver>(
                new AvaloniaXamlIlAvaloniaPropertyResolver(),
                new AvaloniaXamlIlReorderClassesPropertiesTransformer()
                );

            InsertBefore <ContentConvertTransformer>(
                new AvaloniaXamlIlBindingPathParser(),
                new AvaloniaXamlIlSelectorTransformer(),
                new AvaloniaXamlIlControlTemplateTargetTypeMetadataTransformer(),
                new AvaloniaXamlIlPropertyPathTransformer(),
                new AvaloniaXamlIlSetterTransformer(),
                new AvaloniaXamlIlConstructorServiceProviderTransformer(),
                new AvaloniaXamlIlTransitionsTypeMetadataTransformer(),
                new AvaloniaXamlIlResolveByNameMarkupExtensionReplacer()
                );

            // After everything else
            InsertBefore <NewObjectTransformer>(
                new AddNameScopeRegistration(),
                new AvaloniaXamlIlDataContextTypeTransformer(),
                new AvaloniaXamlIlBindingPathTransformer(),
                new AvaloniaXamlIlCompiledBindingsMetadataRemover()
                );

            Transformers.Add(new AvaloniaXamlIlMetadataRemover());
            Transformers.Add(new AvaloniaXamlIlRootObjectScope());

            Emitters.Add(new AvaloniaNameScopeRegistrationXamlIlNodeEmitter());
            Emitters.Add(new AvaloniaXamlIlRootObjectScope.Emitter());
        }
 public XamlImperativeCompiler(TransformerConfiguration configuration,
                               XamlLanguageEmitMappings <TBackendEmitter, TEmitResult> emitMappings, bool fillWithDefaults)
     : base(configuration, emitMappings, fillWithDefaults)
 {
     if (fillWithDefaults)
     {
         Transformers.AddRange(new IXamlAstTransformer[]
         {
             new NewObjectTransformer(),
             new DeferredContentTransformer(),
             new TopDownInitializationTransformer(),
         });
     }
 }
Beispiel #11
0
        internal static (XamlLanguageTypeMappings, XamlLanguageEmitMappings <TBackendEmitter, TEmitResult>) Configure <TBackendEmitter, TEmitResult>(CecilTypeSystem typeSystem)
            where TEmitResult : IXamlEmitResult
        {
            var langaugeMappings = new XamlLanguageTypeMappings(typeSystem, useDefault: false)
            {
                ServiceProvider   = typeSystem.GetType("Microsoft.UI.Xaml.IXamlServiceProvider"),
                ContentAttributes =
                {
                    typeSystem.GetType("Microsoft.UI.Xaml.Markup.ContentPropertyAttribute"),
                    typeSystem.GetType("Windows.UI.Xaml.Markup.ContentPropertyAttribute"),
                }
            };

            var emitMappings = new XamlLanguageEmitMappings <TBackendEmitter, TEmitResult>();

            return(langaugeMappings, emitMappings);
        }
 public AvaloniaXamlIlCompiler(TransformerConfiguration configuration,
                               XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings,
                               IXamlType contextType) : this(configuration, emitMappings)
 {
     _contextType = contextType;
 }
Beispiel #13
0
        static bool?CompileCore(IBuildEngine engine, CecilTypeSystem typeSystem)
        {
            var asm    = typeSystem.TargetAssemblyDefinition;
            var embrsc = new EmbeddedResources(asm);

            if (embrsc.Resources.Count(CheckXamlName) == 0)
            {
                // Nothing to do
                return(null);
            }

            var xamlLanguage = new XamlLanguageTypeMappings(typeSystem)
            {
                XmlnsAttributes =
                {
                    typeSystem.GetType("Avalonia.Metadata.XmlnsDefinitionAttribute"),
                },
                ContentAttributes =
                {
                    typeSystem.GetType("Robust.Client.UserInterface.XAML.ContentAttribute")
                },
                UsableDuringInitializationAttributes =
                {
                    typeSystem.GetType("Robust.Client.UserInterface.XAML.UsableDuringInitializationAttribute")
                },
                DeferredContentPropertyAttributes =
                {
                    typeSystem.GetType("Robust.Client.UserInterface.XAML.DeferredContentAttribute")
                },
                RootObjectProvider = typeSystem.GetType("Robust.Client.UserInterface.XAML.ITestRootObjectProvider"),
                UriContextProvider = typeSystem.GetType("Robust.Client.UserInterface.XAML.ITestUriContext"),
                ProvideValueTarget = typeSystem.GetType("Robust.Client.UserInterface.XAML.ITestProvideValueTarget"),
            };
            var emitConfig = new XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult>
            {
                ContextTypeBuilderCallback = (b, c) => EmitNameScopeField(xamlLanguage, typeSystem, b, c)
            };

            var transformerconfig = new TransformerConfiguration(
                typeSystem,
                typeSystem.TargetAssembly,
                xamlLanguage,
                XamlXmlnsMappings.Resolve(typeSystem, xamlLanguage), CustomValueConverter);

            var contextDef = new TypeDefinition("CompiledRobustXaml", "XamlIlContext",
                                                TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            asm.MainModule.Types.Add(contextDef);
            var contextClass = XamlILContextDefinition.GenerateContextClass(typeSystem.CreateTypeBuilder(contextDef), typeSystem,
                                                                            xamlLanguage, emitConfig);

            var compiler =
                new RobustXamlILCompiler(transformerconfig, emitConfig, true);

            var loaderDispatcherDef = new TypeDefinition("CompiledRobustXaml", "!XamlLoader",
                                                         TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

            var loaderDispatcherMethod = new MethodDefinition("TryLoad",
                                                              MethodAttributes.Static | MethodAttributes.Public,
                                                              asm.MainModule.TypeSystem.Object)
            {
                Parameters = { new ParameterDefinition(asm.MainModule.TypeSystem.String) }
            };

            loaderDispatcherDef.Methods.Add(loaderDispatcherMethod);
            asm.MainModule.Types.Add(loaderDispatcherDef);

            var stringEquals = asm.MainModule.ImportReference(asm.MainModule.TypeSystem.String.Resolve().Methods.First(
                                                                  m =>
                                                                  m.IsStatic && m.Name == "Equals" && m.Parameters.Count == 2 &&
                                                                  m.ReturnType.FullName == "System.Boolean" &&
                                                                  m.Parameters[0].ParameterType.FullName == "System.String" &&
                                                                  m.Parameters[1].ParameterType.FullName == "System.String"));

            bool CompileGroup(IResourceGroup group)
            {
                var typeDef = new TypeDefinition("CompiledRobustXaml", "!" + group.Name, TypeAttributes.Class,
                                                 asm.MainModule.TypeSystem.Object);

                //typeDef.CustomAttributes.Add(new CustomAttribute(ed));
                asm.MainModule.Types.Add(typeDef);
                var builder = typeSystem.CreateTypeBuilder(typeDef);

                foreach (var res in group.Resources.Where(CheckXamlName))
                {
                    try
                    {
                        engine.LogMessage($"XAMLIL: {res.Name} -> {res.Uri}", MessageImportance.Low);

                        var xaml   = new StreamReader(new MemoryStream(res.FileContents)).ReadToEnd();
                        var parsed = XDocumentXamlParser.Parse(xaml);

                        var initialRoot = (XamlAstObjectNode)parsed.Root;

                        var classDirective = initialRoot.Children.OfType <XamlAstXmlDirective>()
                                             .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
                        string classname;
                        if (classDirective != null && classDirective.Values[0] is XamlAstTextNode tn)
                        {
                            classname = tn.Text;
                        }
                        else
                        {
                            classname = res.Name.Replace(".xaml", "");
                        }

                        var classType = typeSystem.TargetAssembly.FindType(classname);
                        if (classType == null)
                        {
                            throw new Exception($"Unable to find type '{classname}'");
                        }

                        compiler.Transform(parsed);

                        var populateName = $"Populate:{res.Name}";
                        var buildName    = $"Build:{res.Name}";

                        var classTypeDefinition = typeSystem.GetTypeReference(classType).Resolve();

                        var populateBuilder = typeSystem.CreateTypeBuilder(classTypeDefinition);

                        compiler.Compile(parsed, contextClass,
                                         compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
                                                                       classTypeDefinition == null),
                                         compiler.DefineBuildMethod(builder, parsed, buildName, true),
                                         null,
                                         (closureName, closureBaseType) =>
                                         populateBuilder.DefineSubType(closureBaseType, closureName, false),
                                         res.Uri, res
                                         );

                        //add compiled populate method
                        var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve().Methods
                                                     .First(m => m.Name == populateName);

                        const string TrampolineName = "!XamlIlPopulateTrampoline";
                        var          trampoline     = new MethodDefinition(TrampolineName,
                                                                           MethodAttributes.Static | MethodAttributes.Private, asm.MainModule.TypeSystem.Void);
                        trampoline.Parameters.Add(new ParameterDefinition(classTypeDefinition));
                        classTypeDefinition.Methods.Add(trampoline);

                        trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
                        trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                        trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, compiledPopulateMethod));
                        trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

                        var foundXamlLoader = false;
                        // Find RobustXamlLoader.Load(this) and replace it with !XamlIlPopulateTrampoline(this)
                        foreach (var method in classTypeDefinition.Methods
                                 .Where(m => !m.Attributes.HasFlag(MethodAttributes.Static)))
                        {
                            var i = method.Body.Instructions;
                            for (var c = 1; c < i.Count; c++)
                            {
                                if (i[c].OpCode == OpCodes.Call)
                                {
                                    var op = i[c].Operand as MethodReference;

                                    if (op != null &&
                                        op.Name == TrampolineName)
                                    {
                                        foundXamlLoader = true;
                                        break;
                                    }

                                    if (op != null &&
                                        op.Name == "Load" &&
                                        op.Parameters.Count == 1 &&
                                        op.Parameters[0].ParameterType.FullName == "System.Object" &&
                                        op.DeclaringType.FullName == "Robust.Client.UserInterface.XAML.RobustXamlLoader")
                                    {
                                        if (MatchThisCall(i, c - 1))
                                        {
                                            i[c].Operand    = trampoline;
                                            foundXamlLoader = true;
                                        }
                                    }
                                }
                            }
                        }

                        if (!foundXamlLoader)
                        {
                            var ctors = classTypeDefinition.GetConstructors()
                                        .Where(c => !c.IsStatic).ToList();
                            // We can inject xaml loader into default constructor
                            if (ctors.Count == 1 && ctors[0].Body.Instructions.Count(o => o.OpCode != OpCodes.Nop) == 3)
                            {
                                var i      = ctors[0].Body.Instructions;
                                var retIdx = i.IndexOf(i.Last(x => x.OpCode == OpCodes.Ret));
                                i.Insert(retIdx, Instruction.Create(OpCodes.Call, trampoline));
                                i.Insert(retIdx, Instruction.Create(OpCodes.Ldarg_0));
                            }
                            else
                            {
                                throw new InvalidProgramException(
                                          $"No call to RobustXamlLoader.Load(this) call found anywhere in the type {classType.FullName} and type seems to have custom constructors.");
                            }
                        }

                        //add compiled build method
                        var compiledBuildMethod = typeSystem.GetTypeReference(builder).Resolve().Methods
                                                  .First(m => m.Name == buildName);
                        var parameterlessCtor = classTypeDefinition.GetConstructors()
                                                .FirstOrDefault(c => c.IsPublic && !c.IsStatic && !c.HasParameters);

                        if (compiledBuildMethod != null && parameterlessCtor != null)
                        {
                            var i   = loaderDispatcherMethod.Body.Instructions;
                            var nop = Instruction.Create(OpCodes.Nop);
                            i.Add(Instruction.Create(OpCodes.Ldarg_0));
                            i.Add(Instruction.Create(OpCodes.Ldstr, res.Uri));
                            i.Add(Instruction.Create(OpCodes.Call, stringEquals));
                            i.Add(Instruction.Create(OpCodes.Brfalse, nop));
                            if (parameterlessCtor != null)
                            {
                                i.Add(Instruction.Create(OpCodes.Newobj, parameterlessCtor));
                            }
                            else
                            {
                                i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
                            }

                            i.Add(Instruction.Create(OpCodes.Ret));
                            i.Add(nop);
                        }
                    }
                    catch (Exception e)
                    {
                        engine.LogErrorEvent(new BuildErrorEventArgs("XAMLIL", "", res.FilePath, 0, 0, 0, 0,
                                                                     $"{res.FilePath}: {e.Message}", "", "CompileRobustXaml"));
                    }
                }
                return(true);
            }

            if (embrsc.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(embrsc))
                {
                    return(false);
                }
            }

            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));
            return(true);
        }
Beispiel #14
0
        private XamlILContextDefinition(IXamlTypeBuilder <IXamlILEmitter> parentBuilder,
                                        IXamlTypeSystem typeSystem, XamlLanguageTypeMappings mappings,
                                        XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings)
        {
            var so      = typeSystem.GetType("System.Object");
            var builder = parentBuilder.DefineSubType(so, "Context", true);

            builder.DefineGenericParameters(new[]
            {
                new KeyValuePair <string, XamlGenericParameterConstraint>("TTarget",
                                                                          new XamlGenericParameterConstraint
                {
                    IsClass = true
                })
            });
            var rootObjectField             = builder.DefineField(builder.GenericParameters[0], "RootObject", true, false);
            var intermediateRootObjectField = builder.DefineField(so, XamlRuntimeContextDefintion.IntermediateRootObjectFieldName, true, false);

            _parentServiceProviderField = builder.DefineField(mappings.ServiceProvider, "_sp", false, false);
            if (mappings.InnerServiceProviderFactoryMethod != null)
            {
                _innerServiceProviderField = builder.DefineField(mappings.ServiceProvider, "_innerSp", false, false);
            }

            var staticProvidersField = builder.DefineField(typeSystem.GetType("System.Object").MakeArrayType(1),
                                                           "_staticProviders", false, false);


            var systemType   = typeSystem.GetType("System.Type");
            var systemUri    = typeSystem.GetType("System.Uri");
            var systemString = typeSystem.GetType("System.String");
            var getServiceInterfaceMethod = mappings.ServiceProvider.FindMethod("GetService", so, false, systemType);

            var ownServices   = new List <IXamlType>();
            var ctorCallbacks = new List <Action <IXamlILEmitter> >();

            if (mappings.RootObjectProvider != null)
            {
                builder.AddInterfaceImplementation(mappings.RootObjectProvider);
                var rootGen = ImplementInterfacePropertyGetter(builder, mappings.RootObjectProvider, XamlRuntimeContextDefintion.RootObjectFieldName)
                              .Generator;
                var tryParent          = rootGen.DefineLabel();
                var fail               = rootGen.DefineLabel();
                var parentRootProvider = rootGen.DefineLocal(mappings.RootObjectProvider);
                rootGen
                // if(RootObject!=null) return RootObject;
                .LdThisFld(rootObjectField)
                .Box(rootObjectField.FieldType)
                .Brfalse(tryParent)
                .LdThisFld(rootObjectField)
                .Box(rootObjectField.FieldType)
                .Ret()
                // if(_sp == null) goto fail;
                .MarkLabel(tryParent)
                .LdThisFld(_parentServiceProviderField)
                .Brfalse(fail)
                // parentProv =  (IRootObjectProvider)_sp.GetService(typeof(IRootObjectProvider));
                .LdThisFld(_parentServiceProviderField)
                .Ldtype(mappings.RootObjectProvider)
                .EmitCall(getServiceInterfaceMethod)
                .Castclass(mappings.RootObjectProvider)
                .Stloc(parentRootProvider)
                // if(parentProv == null) goto fail;
                .Ldloc(parentRootProvider)
                .Brfalse(fail)
                // return parentProv.Root;
                .Ldloc(parentRootProvider)
                .EmitCall(mappings.RootObjectProvider.FindMethod(m => m.Name == "get_RootObject"))
                .Ret()
                // fail:
                .MarkLabel(fail)
                .Ldnull()
                .Ret();

                if (mappings.RootObjectProviderIntermediateRootPropertyName != null)
                {
                    ImplementInterfacePropertyGetter(builder, mappings.RootObjectProvider, mappings.RootObjectProviderIntermediateRootPropertyName)
                    .Generator
                    .LdThisFld(intermediateRootObjectField)
                    .Ret();
                }

                ownServices.Add(mappings.RootObjectProvider);
            }

            if (mappings.ParentStackProvider != null)
            {
                builder.AddInterfaceImplementation(mappings.ParentStackProvider);
                var objectListType = typeSystem.GetType("System.Collections.Generic.List`1")
                                     .MakeGenericType(new[] { typeSystem.GetType("System.Object") });
                ParentListField = builder.DefineField(objectListType, XamlRuntimeContextDefintion.ParentListFieldName, true, false);

                var enumerator = EmitParentEnumerable(typeSystem, parentBuilder, mappings);
                CreateCallbacks.Add(enumerator.createCallback);
                var parentStackEnumerableField = builder.DefineField(
                    typeSystem.GetType("System.Collections.Generic.IEnumerable`1").MakeGenericType(new[] { so }),
                    "_parentStackEnumerable", false, false);

                ImplementInterfacePropertyGetter(builder, mappings.ParentStackProvider, "Parents")
                .Generator.LdThisFld(parentStackEnumerableField).Ret();

                ctorCallbacks.Add(g => g
                                  .Emit(OpCodes.Ldarg_0)
                                  .Emit(OpCodes.Newobj, objectListType.FindConstructor(new List <IXamlType>()))
                                  .Emit(OpCodes.Stfld, ParentListField)
                                  .Emit(OpCodes.Ldarg_0)
                                  .LdThisFld(ParentListField)
                                  .LdThisFld(_parentServiceProviderField)
                                  .Emit(OpCodes.Newobj, enumerator.ctor)
                                  .Emit(OpCodes.Stfld, parentStackEnumerableField));
                ownServices.Add(mappings.ParentStackProvider);
            }

            ownServices.Add(EmitTypeDescriptorContextStub(typeSystem, builder, mappings));

            if (mappings.ProvideValueTarget != null)
            {
                builder.AddInterfaceImplementation(mappings.ProvideValueTarget);
                PropertyTargetObject   = builder.DefineField(so, XamlRuntimeContextDefintion.ProvideTargetObjectName, true, false);
                PropertyTargetProperty = builder.DefineField(so, XamlRuntimeContextDefintion.ProvideTargetPropertyName, true, false);
                ImplementInterfacePropertyGetter(builder, mappings.ProvideValueTarget, "TargetObject")
                .Generator.LdThisFld(PropertyTargetObject).Ret();
                ImplementInterfacePropertyGetter(builder, mappings.ProvideValueTarget, "TargetProperty")
                .Generator.LdThisFld(PropertyTargetProperty).Ret();
                ownServices.Add(mappings.ProvideValueTarget);
            }

            IXamlField baseUriField = null;

            if (mappings.UriContextProvider != null)
            {
                baseUriField = builder.DefineField(systemUri, "_baseUri", false, false);
                builder.AddInterfaceImplementation(mappings.UriContextProvider);
                var getter = builder.DefineMethod(systemUri, new IXamlType[0], "get_BaseUri", true, false, true);
                var setter = builder.DefineMethod(typeSystem.GetType("System.Void"), new[] { systemUri },
                                                  "set_BaseUri", true, false, true);

                getter.Generator
                .LdThisFld(baseUriField)
                .Ret();

                setter.Generator
                .Ldarg_0()
                .Ldarg(1)
                .Stfld(baseUriField)
                .Ret();
                builder.DefineProperty(systemUri, "BaseUri", setter, getter);


                ownServices.Add(mappings.UriContextProvider);
            }

            builder.AddInterfaceImplementation(mappings.ServiceProvider);
            var getServiceMethod = builder.DefineMethod(so,
                                                        new[] { systemType },
                                                        "GetService", true, false, true);

            ownServices = ownServices.Where(s => s != null).ToList();


            if (_innerServiceProviderField != null)
            {
                var next        = getServiceMethod.Generator.DefineLabel();
                var innerResult = getServiceMethod.Generator.DefineLocal(so);
                getServiceMethod.Generator
                //if(_inner == null) goto next;
                .LdThisFld(_innerServiceProviderField)
                .Brfalse(next)
                // var innerRes = _inner.GetService(type);
                .LdThisFld(_innerServiceProviderField)
                .Ldarg(1)
                .EmitCall(getServiceInterfaceMethod)
                .Stloc(innerResult)
                // if(innerRes == null) goto next;
                .Ldloc(innerResult)
                .Brfalse(next)
                // return innerRes
                .Ldloc(innerResult)
                .Ret()
                .MarkLabel(next);
            }
            var compare = systemType.FindMethod("Equals", typeSystem.GetType("System.Boolean"),
                                                false, systemType);
            var isAssignableFrom = systemType.FindMethod("IsAssignableFrom", typeSystem.GetType("System.Boolean"),
                                                         false, systemType);
            var fromHandle        = systemType.Methods.First(m => m.Name == "GetTypeFromHandle");
            var getTypeFromObject = so.Methods.First(m => m.Name == "GetType" && m.Parameters.Count == 0);

            if (ownServices.Count != 0)
            {
                for (var c = 0; c < ownServices.Count; c++)
                {
                    var next = getServiceMethod.Generator.DefineLabel();
                    getServiceMethod.Generator
                    .Emit(OpCodes.Ldtoken, ownServices[c])
                    .EmitCall(fromHandle)
                    .Emit(OpCodes.Ldarg_1)
                    .Emit(OpCodes.Callvirt, compare)
                    .Emit(OpCodes.Brfalse, next)
                    .Emit(OpCodes.Ldarg_0)
                    .Emit(OpCodes.Ret)
                    .MarkLabel(next);
                }
            }

            var staticProviderIndex   = getServiceMethod.Generator.DefineLocal(typeSystem.GetType("System.Int32"));
            var staticProviderNext    = getServiceMethod.Generator.DefineLabel();
            var staticProviderFailed  = getServiceMethod.Generator.DefineLabel();
            var staticProviderEnd     = getServiceMethod.Generator.DefineLabel();
            var staticProviderElement = getServiceMethod.Generator.DefineLocal(so);

            getServiceMethod.Generator
            //start: if(_staticProviders == null) goto: end
            .LdThisFld(staticProvidersField)
            .Brfalse(staticProviderEnd)
            // var c = 0
            .Ldc_I4(0)
            .Stloc(staticProviderIndex)
            // next:
            .MarkLabel(staticProviderNext)
            // if(c >= _staticProviders.Length) goto: end
            .Ldloc(staticProviderIndex)
            .LdThisFld(staticProvidersField)
            .Ldlen()
            .Bge(staticProviderEnd)
            // var obj = _staticProviders[c]
            .LdThisFld(staticProvidersField)
            .Ldloc(staticProviderIndex)
            .Ldelem_ref()
            // dup
            .Stloc(staticProviderElement)
            .Ldarg(1)
            .Ldloc(staticProviderElement)
            // if(obj.GetType().Equals(arg1)) return obj; else goto failed;
            .EmitCall(getTypeFromObject)
            .EmitCall(isAssignableFrom)
            .Brfalse(staticProviderFailed)
            .Ldloc(staticProviderElement)
            .Ret()
            // failed:
            .MarkLabel(staticProviderFailed)
            // c++
            .Ldloc(staticProviderIndex)
            .Ldc_I4(1)
            .Add()
            .Stloc(staticProviderIndex)
            // goto: start
            .Br(staticProviderNext)
            // end:
            .MarkLabel(staticProviderEnd);

            var noParentProvider = getServiceMethod.Generator.DefineLabel();

            getServiceMethod.Generator
            .LdThisFld(_parentServiceProviderField)
            .Brfalse(noParentProvider)
            .LdThisFld(_parentServiceProviderField)
            .Ldarg(1)
            .EmitCall(getServiceInterfaceMethod)
            .Emit(OpCodes.Ret)
            .MarkLabel(noParentProvider)
            .Ldnull()
            .Ret();

            var ctor = builder.DefineConstructor(false,
                                                 mappings.ServiceProvider,
                                                 staticProvidersField.FieldType,
                                                 systemString);

            ctor.Generator
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Call, so.Constructors.First())
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Ldarg_1)
            .Emit(OpCodes.Stfld, _parentServiceProviderField)
            .Emit(OpCodes.Ldarg_0)
            .Emit(OpCodes.Ldarg_2)
            .Emit(OpCodes.Stfld, staticProvidersField);
            if (baseUriField != null)
            {
                var noUri = ctor.Generator.DefineLabel();
                ctor.Generator
                .Emit(OpCodes.Ldarg_3)
                .Brfalse(noUri)
                .Emit(OpCodes.Ldarg_0)
                .Emit(OpCodes.Ldarg_3)
                .Newobj(systemUri.FindConstructor(new List <IXamlType>
                {
                    typeSystem.GetType("System.String")
                }))
                .Emit(OpCodes.Stfld, baseUriField)
                .MarkLabel(noUri);
            }

            foreach (var feature in ctorCallbacks)
            {
                feature(ctor.Generator);
            }

            emitMappings.ContextTypeBuilderCallback?.Invoke(builder, ctor.Generator);

            // We are calling this last to ensure that our own services are ready
            if (_innerServiceProviderField != null)
            {
                ctor.Generator
                // _innerSp = InnerServiceProviderFactory(this)
                .Ldarg_0()
                .Ldarg_0()
                .EmitCall(mappings.InnerServiceProviderFactoryMethod)
                .Stfld(_innerServiceProviderField);
            }

            ctor.Generator.Emit(OpCodes.Ret);

            Constructor = ctor;
            CreateCallbacks.Add(() => { parentBuilder.CreateType(); });

            if (ParentListField != null)
            {
                EmitPushPopParent(builder, typeSystem);
            }

            CreateAllTypes();
            ContextType = builder.CreateType();
        }
Beispiel #15
0
 public static IXamlType GenerateContextClass(IXamlTypeBuilder <IXamlILEmitter> builder,
                                              IXamlTypeSystem typeSystem, XamlLanguageTypeMappings mappings,
                                              XamlLanguageEmitMappings <IXamlILEmitter, XamlILNodeEmitResult> emitMappings)
 {
     return(new XamlILContextDefinition(builder, typeSystem, mappings, emitMappings).ContextType);
 }