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