Exemple #1
0
        private static void AddIComponentRazorViewFactoryImplementation(ClassDeclarationIRNode classNode)
        {
            // The Activator.CreateInstance feature that I added to the DNA runtime is very basic and doesn't
            // actually invoke the default constructor of the type being created. It just allocates memory for
            // the instance and returns it, without having run any constructor. This could be confusing if you
            // put constructor logic (such as field initializers) in your Razor page, given that we instantiate
            // it using Activator.CreateInstance.
            // As a workaround (without actually adding constructor support to Activator.CreateInstance, which
            // would be nontrivial), the Razor views privately implement an interface IComponentRazorViewFactory
            // that can return new instances of their own type. We can then just call this with normal .NET code.
            // This means we allocate memory for two instances of the view even though we're only using one,
            // but it's not going to matter much as the first instance will just be released to GC immediately.
            if (classNode.Interfaces == null)
            {
                classNode.Interfaces = new List <string>();
            }
            classNode.Interfaces.Add(typeof(IRazorComponentFactory).FullName);
            var methodStatement = new CSharpStatementIRNode {
                Parent = classNode, Source = null
            };

            classNode.Children.Add(methodStatement);
            methodStatement.Children.Add(new RazorIRToken
            {
                Kind    = RazorIRToken.TokenKind.CSharp,
                Parent  = classNode,
                Content = $@"
                    {typeof(RazorComponent).FullName} {typeof(IRazorComponentFactory).FullName}.{nameof(IRazorComponentFactory.Instantiate)}()
                    {{
                        return new {classNode.Name}();
                    }}"
            });
        }
            public override void VisitClassDeclaration(ClassDeclarationIRNode node)
            {
                if (ClassNode == null)
                {
                    ClassNode = node;
                }

                VisitDefault(node);
            }
Exemple #3
0
            public override void VisitClassDeclaration(ClassDeclarationIRNode node)
            {
                Context.Writer
                .Write(node.AccessModifier)
                .Write(" class ")
                .Write(node.Name);

                if (node.BaseType != null || node.Interfaces != null)
                {
                    Context.Writer.Write(" : ");
                }

                if (node.BaseType != null)
                {
                    Context.Writer.Write(node.BaseType);

                    if (node.Interfaces != null)
                    {
                        Context.Writer.WriteParameterSeparator();
                    }
                }

                if (node.Interfaces != null)
                {
                    for (var i = 0; i < node.Interfaces.Count; i++)
                    {
                        Context.Writer.Write(node.Interfaces[i]);

                        if (i + 1 < node.Interfaces.Count)
                        {
                            Context.Writer.WriteParameterSeparator();
                        }
                    }
                }

                Context.Writer.WriteLine();

                using (Context.Writer.BuildScope())
                {
                    RenderChildren(node);
                }
            }
Exemple #4
0
        private static void AddIComponentRazorViewFactoryImplementation(ClassDeclarationIRNode classNode, RazorCodeDocument codeDoc)
        {
            // The Activator.CreateInstance feature that I added to the DNA runtime is very basic and doesn't
            // actually invoke the default constructor of the type being created. It just allocates memory for
            // the instance and returns it, without having run any constructor. This could be confusing if you
            // put constructor logic (such as field initializers) in your Razor page, given that we instantiate
            // it using Activator.CreateInstance.
            // As a workaround (without actually adding constructor support to Activator.CreateInstance, which
            // would be nontrivial), the Razor views privately implement an interface IComponentRazorViewFactory
            // that can return new instances of their own type. We can then just call this with normal .NET code.
            // This means we allocate memory for two instances of the view even though we're only using one,
            // but it's not going to matter much as the first instance will just be released to GC immediately.
            if (classNode.Interfaces == null)
            {
                classNode.Interfaces = new List <string>();
            }
            classNode.Interfaces.Add(typeof(IRazorComponentFactory).FullName);
            var methodStatement = new CSharpStatementIRNode {
                Parent = classNode, Source = null
            };

            classNode.Children.Add(methodStatement);

            var    model    = codeDoc.Items["DetectedModel"];
            string content  = "";
            string isPage   = "";
            string addItems = "";

            if (model != null)
            {
                content = $@"Model = new {model}();";
            }
            if ((bool)codeDoc.Items["DetectedPage"])
            {
                isPage += "classNode.IsPage = true;";
            }

            if ((codeDoc.Items["DetectedPageMatches"]) != null)
            {
                var list = (List <string>)codeDoc.Items["DetectedPageMatches"];
                addItems += "List<string> list = new List<string>();";
                foreach (var item in list)
                {
                    addItems += $"\r\n list.Add(\"{item}\");";
                }
                addItems += "\r\n Items = list;";
            }
            var razorToken = new RazorIRToken
            {
                Kind    = RazorIRToken.TokenKind.CSharp,
                Parent  = classNode,
                Content = $@"
                    {typeof(RazorComponent).FullName} {typeof(IRazorComponentFactory).FullName}.{nameof(IRazorComponentFactory.Instantiate)}()
                    {{
                        {content} 
                        var classNode = new {classNode.Name}();
                        {isPage}
                        {addItems}
                        return classNode;
                    }}"
            };

            methodStatement.Children.Add(razorToken);
        }