示例#1
0
        public static Func <IServiceProvider, object> Compile(string xaml)
        {
            // Enforce everything to load
            foreach (var xt in typeof(BenchCompiler).Assembly.GetTypes())
            {
                xt.GetCustomAttributes();
                xt.GetInterfaces();
                foreach (var p in xt.GetProperties())
                {
                    p.GetCustomAttributes();
                }
            }
            typeof(IXamlIlParentStackProviderV1).Assembly.GetCustomAttributes();


            var typeSystem    = new SreTypeSystem();
            var configuration = BenchmarksXamlIlConfiguration.Configure(typeSystem);
            var parsed        = XDocumentXamlIlParser.Parse(xaml);

            var compiler = new XamlIlCompiler(configuration, true);

            compiler.Transform(parsed);


            var parsedTsType = ((IXamlIlAstValueNode)parsed.Root).Type.GetClrType();

#if !NETCOREAPP
            var path = Path.GetDirectoryName(typeof(BenchCompiler).Assembly.GetModules()[0].FullyQualifiedName);
            var da   = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString("N")),
                                                                     AssemblyBuilderAccess.RunAndSave,
                                                                     path);
#else
            var da = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString("N")), AssemblyBuilderAccess.Run);
#endif

            var dm = da.DefineDynamicModule("testasm.dll");
            var t  = dm.DefineType(Guid.NewGuid().ToString("N"), TypeAttributes.Public);

            var ctb            = dm.DefineType(t.Name + "Context", TypeAttributes.Public);
            var contextTypeDef = compiler.CreateContextType(((SreTypeSystem)typeSystem).CreateTypeBuilder(ctb));

            var parserTypeBuilder = ((SreTypeSystem)typeSystem).CreateTypeBuilder(t);
            compiler.Compile(parsed, parserTypeBuilder, contextTypeDef, "Populate", "Build",
                             "XamlIlNamespaceInfo", "https://github.com/kekekeks/XamlIl", null);

            var created = t.CreateType();

#if !NETCOREAPP
            dm.CreateGlobalFunctions();
            // Useful for debugging the actual MSIL, don't remove
            lock (s_asmLock)
                da.Save("testasm.dll");
#endif

            var isp = Expression.Parameter(typeof(IServiceProvider));
            return(Expression.Lambda <Func <IServiceProvider, object> >(
                       Expression.Convert(Expression.Call(
                                              created.GetMethod("Build"), isp), typeof(object)), isp).Compile());
        }
示例#2
0
        XamlIlDocument Compile(IXamlIlTypeBuilder builder, IXamlIlType context, string xaml)
        {
            var parsed   = XDocumentXamlIlParser.Parse(xaml);
            var compiler = new XamlIlCompiler(Configuration, true);

            compiler.Transform(parsed);
            compiler.Compile(parsed, builder, context, "Populate", "Build",
                             "XamlIlNamespaceInfo",
                             "http://example.com/", null);
            return(parsed);
        }
示例#3
0
        public void Parser_Should_Handle_Ignorable_Content(bool map)
        {
            var root = XDocumentXamlIlParser.Parse(@"
<Root xmlns='rootns' xmlns:mc='http://schemas.openxmlformats.org/markup-compatibility/2006' 
    mc:Ignorable='d d2' xmlns:d='test' xmlns:d2='test2'
    d:DataContext='123' d2:Lalala='321'>
    <d:DesignWidth>test</d:DesignWidth>
</Root>
 ", map ? new Dictionary <string, string>()
            {
                ["test"] = "mapped"
            } : null);
            var ni       = new NullLineInfo();
            var rootType = new XamlIlAstXmlTypeReference(ni, "rootns", "Root");

            if (map)
            {
                Helpers.StructDiff(root.Root, new XamlIlAstObjectNode(ni, rootType)
                {
                    Children =
                    {
                        new XamlIlAstXmlDirective(ni,     "mapped",                         "DataContext", new[] { new XamlIlAstTextNode(ni, "123"), }),
                        new XamlIlAstObjectNode(ni,       new XamlIlAstXmlTypeReference(ni, "mapped",      "DesignWidth"))
                        {
                            Children =
                            {
                                new XamlIlAstTextNode(ni, "test")
                            }
                        }
                    }
                });
            }
            else
            {
                Helpers.StructDiff(root.Root, new XamlIlAstObjectNode(ni, rootType)
                {
                });
            }
        }
示例#4
0
        public static CompileResult Compile(IBuildEngine engine, string input, string[] references, string projectDirectory,
                                            string output)
        {
            var typeSystem = new CecilTypeSystem(references.Concat(new[] { input }), input);
            var asm        = typeSystem.TargetAssemblyDefinition;
            var emres      = new EmbeddedResources(asm);
            var avares     = new AvaloniaResources(asm, projectDirectory);

            if (avares.Resources.Count(CheckXamlName) == 0 && emres.Resources.Count(CheckXamlName) == 0)
            {
                // Nothing to do
                return(new CompileResult(true));
            }

            var xamlLanguage   = AvaloniaXamlIlLanguage.Configure(typeSystem);
            var compilerConfig = new XamlIlTransformerConfiguration(typeSystem,
                                                                    typeSystem.TargetAssembly,
                                                                    xamlLanguage,
                                                                    XamlIlXmlnsMappings.Resolve(typeSystem, xamlLanguage),
                                                                    AvaloniaXamlIlLanguage.CustomValueConverter);


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

            asm.MainModule.Types.Add(contextDef);

            var contextClass = XamlIlContextDefinition.GenerateContextClass(typeSystem.CreateTypeBuilder(contextDef), typeSystem,
                                                                            xamlLanguage);

            var compiler = new AvaloniaXamlIlCompiler(compilerConfig, contextClass);

            var editorBrowsableAttribute = typeSystem
                                           .GetTypeReference(typeSystem.FindType("System.ComponentModel.EditorBrowsableAttribute"))
                                           .Resolve();
            var editorBrowsableCtor =
                asm.MainModule.ImportReference(editorBrowsableAttribute.GetConstructors()
                                               .First(c => c.Parameters.Count == 1));

            var runtimeHelpers = typeSystem.GetType("Avalonia.Markup.Xaml.XamlIl.Runtime.XamlIlRuntimeHelpers");
            var createRootServiceProviderMethod = asm.MainModule.ImportReference(
                typeSystem.GetTypeReference(runtimeHelpers).Resolve().Methods
                .First(x => x.Name == "CreateRootServiceProviderV2"));

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


            loaderDispatcherDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor)
            {
                ConstructorArguments = { new CustomAttributeArgument(editorBrowsableCtor.Parameters[0].ParameterType, 1) }
            });


            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("CompiledAvaloniaXaml", "!" + group.Name,
                                                 TypeAttributes.Class, asm.MainModule.TypeSystem.Object);

                typeDef.CustomAttributes.Add(new CustomAttribute(editorBrowsableCtor)
                {
                    ConstructorArguments = { new CustomAttributeArgument(editorBrowsableCtor.Parameters[0].ParameterType, 1) }
                });
                asm.MainModule.Types.Add(typeDef);
                var builder = typeSystem.CreateTypeBuilder(typeDef);

                foreach (var res in group.Resources.Where(CheckXamlName))
                {
                    try
                    {
                        // StreamReader is needed here to handle BOM
                        var xaml   = new StreamReader(new MemoryStream(res.FileContents)).ReadToEnd();
                        var parsed = XDocumentXamlIlParser.Parse(xaml);

                        var initialRoot = (XamlIlAstObjectNode)parsed.Root;


                        var precompileDirective = initialRoot.Children.OfType <XamlIlAstXmlDirective>()
                                                  .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Precompile");
                        if (precompileDirective != null)
                        {
                            var precompileText = (precompileDirective.Values[0] as XamlIlAstTextNode)?.Text.Trim()
                                                 .ToLowerInvariant();
                            if (precompileText == "false")
                            {
                                continue;
                            }
                            if (precompileText != "true")
                            {
                                throw new XamlIlParseException("Invalid value for x:Precompile", precompileDirective);
                            }
                        }

                        var classDirective = initialRoot.Children.OfType <XamlIlAstXmlDirective>()
                                             .FirstOrDefault(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Class");
                        IXamlIlType classType = null;
                        if (classDirective != null)
                        {
                            if (classDirective.Values.Count != 1 || !(classDirective.Values[0] is XamlIlAstTextNode tn))
                            {
                                throw new XamlIlParseException("x:Class should have a string value", classDirective);
                            }
                            classType = typeSystem.TargetAssembly.FindType(tn.Text);
                            if (classType == null)
                            {
                                throw new XamlIlParseException($"Unable to find type `{tn.Text}`", classDirective);
                            }
                            compiler.OverrideRootType(parsed,
                                                      new XamlIlAstClrTypeReference(classDirective, classType, false));
                            initialRoot.Children.Remove(classDirective);
                        }


                        compiler.Transform(parsed);
                        var populateName = classType == null ? "Populate:" + res.Name : "!XamlIlPopulate";
                        var buildName    = classType == null ? "Build:" + res.Name : null;

                        var classTypeDefinition =
                            classType == null ? null : typeSystem.GetTypeReference(classType).Resolve();


                        var populateBuilder = classTypeDefinition == null ?
                                              builder :
                                              typeSystem.CreateTypeBuilder(classTypeDefinition);
                        compiler.Compile(parsed, contextClass,
                                         compiler.DefinePopulateMethod(populateBuilder, parsed, populateName,
                                                                       classTypeDefinition == null),
                                         buildName == null ? null : compiler.DefineBuildMethod(builder, parsed, buildName, true),
                                         builder.DefineSubType(compilerConfig.WellKnownTypes.Object, "NamespaceInfo:" + res.Name,
                                                               true),
                                         (closureName, closureBaseType) =>
                                         populateBuilder.DefineSubType(closureBaseType, closureName, false),
                                         res.Uri, res
                                         );


                        if (classTypeDefinition != null)
                        {
                            var compiledPopulateMethod = typeSystem.GetTypeReference(populateBuilder).Resolve()
                                                         .Methods.First(m => m.Name == populateName);

                            var designLoaderFieldType = typeSystem
                                                        .GetType("System.Action`1")
                                                        .MakeGenericType(typeSystem.GetType("System.Object"));

                            var designLoaderFieldTypeReference = (GenericInstanceType)typeSystem.GetTypeReference(designLoaderFieldType);
                            designLoaderFieldTypeReference.GenericArguments[0] =
                                asm.MainModule.ImportReference(designLoaderFieldTypeReference.GenericArguments[0]);
                            designLoaderFieldTypeReference = (GenericInstanceType)
                                                             asm.MainModule.ImportReference(designLoaderFieldTypeReference);

                            var designLoaderLoad =
                                typeSystem.GetMethodReference(
                                    designLoaderFieldType.Methods.First(m => m.Name == "Invoke"));
                            designLoaderLoad =
                                asm.MainModule.ImportReference(designLoaderLoad);
                            designLoaderLoad.DeclaringType = designLoaderFieldTypeReference;

                            var designLoaderField = new FieldDefinition("!XamlIlPopulateOverride",
                                                                        FieldAttributes.Static | FieldAttributes.Private, designLoaderFieldTypeReference);
                            classTypeDefinition.Fields.Add(designLoaderField);

                            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);

                            var regularStart = Instruction.Create(OpCodes.Call, createRootServiceProviderMethod);

                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Brfalse, regularStart));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldsfld, designLoaderField));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Call, designLoaderLoad));
                            trampoline.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

                            trampoline.Body.Instructions.Add(regularStart);
                            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));
                            CopyDebugDocument(trampoline, compiledPopulateMethod);

                            var foundXamlLoader = false;
                            // Find AvaloniaXamlLoader.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;

                                        // TODO: Throw an error
                                        // This usually happens when same XAML resource was added twice for some weird reason
                                        // We currently support it for dual-named default theme resource
                                        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 == "Avalonia.Markup.Xaml.AvaloniaXamlLoader")
                                        {
                                            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 AvaloniaXamlLoader.Load(this) call found anywhere in the type {classType.FullName} and type seems to have custom constructors.");
                                }
                            }
                        }

                        if (buildName != null || classTypeDefinition != null)
                        {
                            var compiledBuildMethod = buildName == null ?
                                                      null :
                                                      typeSystem.GetTypeReference(builder).Resolve()
                                                      .Methods.First(m => m.Name == buildName);
                            var parameterlessConstructor = compiledBuildMethod != null ?
                                                           null :
                                                           classTypeDefinition.GetConstructors().FirstOrDefault(c =>
                                                                                                                c.IsPublic && !c.IsStatic && !c.HasParameters);

                            if (compiledBuildMethod != null || parameterlessConstructor != 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 (parameterlessConstructor != null)
                                {
                                    i.Add(Instruction.Create(OpCodes.Newobj, parameterlessConstructor));
                                }
                                else
                                {
                                    i.Add(Instruction.Create(OpCodes.Call, createRootServiceProviderMethod));
                                    i.Add(Instruction.Create(OpCodes.Call, compiledBuildMethod));
                                }

                                i.Add(Instruction.Create(OpCodes.Ret));
                                i.Add(nop);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        int lineNumber = 0, linePosition = 0;
                        if (e is XamlIlParseException xe)
                        {
                            lineNumber   = xe.LineNumber;
                            linePosition = xe.LinePosition;
                        }
                        engine.LogErrorEvent(new BuildErrorEventArgs("Avalonia", "XAMLIL", res.FilePath,
                                                                     lineNumber, linePosition, lineNumber, linePosition,
                                                                     e.Message, "", "Avalonia"));
                        return(false);
                    }
                    res.Remove();
                }
                return(true);
            }

            if (emres.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(emres))
                {
                    return(new CompileResult(false));
                }
            }
            if (avares.Resources.Count(CheckXamlName) != 0)
            {
                if (!CompileGroup(avares))
                {
                    return(new CompileResult(false));
                }
                avares.Save();
            }

            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ldnull));
            loaderDispatcherMethod.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

            asm.Write(output, new WriterParameters
            {
                WriteSymbols = asm.MainModule.HasSymbols
            });

            return(new CompileResult(true, true));
        }
示例#5
0
        public void Parser_Should_Be_Able_To_Parse_A_Simple_Tree()
        {
            var root = XDocumentXamlIlParser.Parse(
                @"
<Root xmlns='rootns' xmlns:t='testns' xmlns:d='directive' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
    <Child Ext='{Extension 123, 321, Prop=test, Prop2=test2, Prop3={Extension}, Prop4=test3}'
        Other.Prop='{}Not extension'
        Prop1='123' 
        Root.AttachedProp='AttachedValue'
        t:Namespaced.AttachedProp='AttachedValue'
        d:Directive='DirectiveValue'
        d:DirectiveExt='{Extension 123}'>
        <t:SubChild Prop='321' Root.AttachedProp='AttachedValue'/>
        <Child.DottedProp>DottedValue</Child.DottedProp>
        <Root.AttachedDottedProp>AttachedValue</Root.AttachedDottedProp>
        <Child.NodeListProp>
            <SubChild/>
            <SubChild/>
        </Child.NodeListProp>
    </Child>
    <GenericType x:TypeArguments='Child,t:NamespacedGeneric(Child,GenericType ( Child, t:Namespaced) )'/>

</Root>");
            var ni             = new NullLineInfo();
            var rootType       = new XamlIlAstXmlTypeReference(ni, "rootns", "Root");
            var childType      = new XamlIlAstXmlTypeReference(ni, "rootns", "Child");
            var subChildType   = new XamlIlAstXmlTypeReference(ni, "rootns", "SubChild");
            var nsSubChildType = new XamlIlAstXmlTypeReference(ni, "testns", "SubChild");
            var namespacedType = new XamlIlAstXmlTypeReference(ni, "testns", "Namespaced");
            var extensionType  = new XamlIlAstXmlTypeReference(ni, "rootns", "Extension")
            {
                IsMarkupExtension = true
            };

            var other = new XamlIlDocument
            {
                NamespaceAliases = new Dictionary <string, string>
                {
                    [""]  = "rootns",
                    ["t"] = "testns",
                    ["d"] = "directive",
                    ["x"] = "http://schemas.microsoft.com/winfx/2006/xaml"
                },
                Root = new XamlIlAstObjectNode(ni, rootType)
                {
                    Children =
                    {
                        // <Child
                        new XamlIlAstObjectNode(ni,                                                                                                                                 childType)
                        {
                            Children =
                            {
                                // Ext='{Extension 123, 321, Prop=test, Prop2=test2}'
                                new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                              new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                       childType,                                                                                                                                                "Ext",                                                                                                                                             childType),
                                                                   new XamlIlAstObjectNode(ni,                                                                                                                                                                      extensionType)
                                {
                                    Arguments =
                                    {
                                        new XamlIlAstTextNode(ni, "123"),
                                        new XamlIlAstTextNode(ni, "321"),
                                    },
                                    Children =
                                    {
                                        new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                                                                                                                                                                                         new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          extensionType,                                                                                                                                                                                                                                                                                                       "Prop",                                                                                                                                            extensionType),
                                                                           new XamlIlAstTextNode(ni,                                                                                                                                                                                                                                                                                                                                   "test")),
                                        new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                                                                                                                                                                                         new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          extensionType,                                                                                                                                                                                                                                                                                                       "Prop2",                                                                                                                                           extensionType),
                                                                           new XamlIlAstTextNode(ni,                                                                                                                                                                                                                                                                                                                                   "test2")),
                                        new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                                                                                                                                                                                         new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          extensionType,                                                                                                                                                                                                                                                                                                       "Prop3",                                                                                                                                           extensionType),
                                                                           new XamlIlAstObjectNode(ni,                                                                                                                                                                                                                                                                                                                                 extensionType)),
                                        new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                                                                                                                                                                                         new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          extensionType,                                                                                                                                                                                                                                                                                                       "Prop4",                                                                                                                                           extensionType),
                                                                           new XamlIlAstTextNode(ni,                                                                                                                                                                                                                                                                                                                                   "test3")),
                                    }
                                }),
                                //Other.Prop='{}Not extension'
                                new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                              new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                       new XamlIlAstXmlTypeReference(ni,                                                                                                                         "rootns",                                                                                                                                          "Other"),                                 "Prop", childType),
                                                                   new XamlIlAstTextNode(ni,                                                                                                                                                                        "Not extension")),
                                //  Prop1='123'
                                new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                              new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                       childType,                                                                                                                                                "Prop1",                                                                                                                                           childType),
                                                                   new XamlIlAstTextNode(ni,                                                                                                                                                                        "123")),
                                // Root.AttachedProp='AttachedValue'
                                new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                              new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                       rootType,                                                                                                                                                 "AttachedProp",                                                                                                                                    childType),
                                                                   new XamlIlAstTextNode(ni,                                                                                                                                                                        "AttachedValue")),
                                //t:Namespaced.AttachedProp='AttachedValue'
                                new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                              new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                       namespacedType,                                                                                                                                           "AttachedProp",                                                                                                                                    childType),
                                                                   new XamlIlAstTextNode(ni,                                                                                                                                                                        "AttachedValue")),
                                //d:Directive='DirectiveValue'>
                                new XamlIlAstXmlDirective(ni,                                                                                                                                                                                                       "directive",                                                                                                                                       "Directive",                              new[]
                                {
                                    new XamlIlAstTextNode(ni,                                                                                                                                                                                                       "DirectiveValue")
                                }),
                                //d:DirectiveExt='{Extension 123}'>
                                new XamlIlAstXmlDirective(ni,                                                                                                                                                                                                       "directive",                                                                                                                                       "DirectiveExt",                           new[]
                                {
                                    new XamlIlAstObjectNode(ni,                                                                                                                                                                                                     extensionType)
                                    {
                                        Arguments =
                                        {
                                            new XamlIlAstTextNode(ni, "123"),
                                        }
                                    }
                                }),
                                // <t:SubChild Prop='321' Root.AttachedProp='AttachedValue'/>
                                new XamlIlAstObjectNode(ni,                                                                                                                                                                                                         nsSubChildType)
                                {
                                    Children =
                                    {
                                        new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                                                                                                                                                                                          new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                           nsSubChildType,                                                                                                                                                                                                                                                                                                       "Prop",                                                                                                                                            nsSubChildType),
                                                                           new XamlIlAstTextNode(ni,                                                                                                                                                                                                                                                                                                                                    "321")),
                                        // Root.AttachedProp='AttachedValue'
                                        new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                                                                                                                                                                                          new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                           rootType,                                                                                                                                                                                                                                                                                                             "AttachedProp",                                                                                                                                    nsSubChildType),
                                                                           new XamlIlAstTextNode(ni,                                                                                                                                                                                                                                                                                                                                    "AttachedValue")),
                                    }
                                },
                                //<Child.DottedProp>DottedValue</Child.DottedProp>
                                new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                              new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                       childType,                                                                                                                                                "DottedProp",                                                                                                                                      childType),
                                                                   new[]
                                {
                                    new XamlIlAstTextNode(ni,                                                                                                                                                                                                       "DottedValue")
                                }),
                                // <Root.AttachedDottedProp>AttachedValue</Root.AttachedDottedProp>
                                new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                              new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                       rootType,                                                                                                                                                 "AttachedDottedProp",                                                                                                                              childType),
                                                                   new[]
                                {
                                    new XamlIlAstTextNode(ni,                                                                                                                                                                                                       "AttachedValue")
                                }),
                                //<Child.NodeListProp>
                                new XamlIlAstXamlPropertyValueNode(ni,                                                                                                                                                                                              new XamlIlAstNamePropertyReference(ni,
                                                                                                                                                                                                                                                                                                       childType,                                                                                                                                                "NodeListProp",                                                                                                                                    childType),
                                                                   new[]
                                {
                                    // <SubChild/>
                                    new XamlIlAstObjectNode(ni,                                                                                                                                                                                                     subChildType),
                                    // <SubChild/>
                                    new XamlIlAstObjectNode(ni,                                                                                                                                                                                                     subChildType),
                                })
                            }
                        },
                        //<GenericType x:TypeArguments='Child,t:NamespacedGeneric(Child,GenericType(Child, t:Namespaced))'/>
                        new XamlIlAstObjectNode(ni,                                                                                                                                 new XamlIlAstXmlTypeReference(ni,     "rootns",             "GenericType",
                                                                                                                                                                                                                  new[]
                        {
                            childType,
                            new XamlIlAstXmlTypeReference(ni,                                                                                                                       "testns",                             "NamespacedGeneric",  new[]
                            {
                                childType,
                                new XamlIlAstXmlTypeReference(ni,                                                                                                                   "rootns",                             "GenericType",        new[]
                                {
                                    childType,
                                    namespacedType
                                }),
                            }),
                        }))
                    }
                }
            };

            Helpers.StructDiff(root, other);
        }
示例#6
0
        protected (Func <IServiceProvider, object> create, Action <IServiceProvider, object> populate) Compile(string xaml)
        {
            var parsed = XDocumentXamlIlParser.Parse(xaml);

            var compiler = new XamlIlAstTransformationManager(Configuration, true);

            compiler.Transform(parsed, parsed.NamespaceAliases);


            var parsedTsType = ((IXamlIlAstValueNode)parsed.Root).Type.GetClrType();
            var parsedType   =
                ((SreTypeSystem)_typeSystem).GetType(parsedTsType);

            #if !NETCOREAPP
            var da = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString("N")),
                                                                   AssemblyBuilderAccess.RunAndSave,
                                                                   Directory.GetCurrentDirectory());
            #else
            var da = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(Guid.NewGuid().ToString("N")), AssemblyBuilderAccess.Run);
            #endif

            var dm           = da.DefineDynamicModule("testasm.dll");
            var t            = dm.DefineType(Guid.NewGuid().ToString("N"), TypeAttributes.Public);
            var createMethod = t.DefineMethod("Build", MethodAttributes.Static | MethodAttributes.Public,
                                              parsedType, new[] { typeof(IServiceProvider) });
            var createGen = ((SreTypeSystem)_typeSystem).CreateCodeGen(createMethod);

            var populateMethod = t.DefineMethod("Populate", MethodAttributes.Static | MethodAttributes.Public,
                                                typeof(void), new [] { typeof(IServiceProvider), parsedType });
            var populateGen = ((SreTypeSystem)_typeSystem).CreateCodeGen(populateMethod);


            var contextClass = XamlIlContext.GenerateContextClass(((SreTypeSystem)_typeSystem).CreateTypeBuilder(
                                                                      dm.DefineType(t.Name + "_Context", TypeAttributes.Public)),
                                                                  _typeSystem, Configuration.TypeMappings, parsedTsType);

            compiler.Compile(parsed.Root, createGen, contextClass, false);
            compiler.Compile(parsed.Root, populateGen, contextClass, true);

            var created = t.CreateType();
            #if !NETCOREAPP
            dm.CreateGlobalFunctions();
            // Useful for debugging the actual MSIL, don't remove
            lock (s_asmLock)
                da.Save("testasm.dll");
            #endif



            var isp      = Expression.Parameter(typeof(IServiceProvider));
            var createCb = Expression.Lambda <Func <IServiceProvider, object> >(
                Expression.Convert(Expression.Call(
                                       created.GetMethod("Build"), isp), typeof(object)), isp).Compile();


            var epar = Expression.Parameter(typeof(object));
            isp = Expression.Parameter(typeof(IServiceProvider));
            var populateCb = Expression.Lambda <Action <IServiceProvider, object> >(
                Expression.Call(created.GetMethod("Populate"), isp, Expression.Convert(epar, parsedType)),
                isp, epar).Compile();

            return(createCb, populateCb);
        }