public override IEnumerable <CodeComponent <TAttribute> > GetComponents <TAttribute>() { if (Items != null) { foreach (PObject item in Items) { if (!item.HasAttribute <TAttribute>()) { continue; } var attr = item.GetAttribute <TAttribute>(); var component = new CodeComponent <TAttribute>(item, attr); var stack = new Stack <CodeComponent <TAttribute> >(new[] { component }); while (stack.Count > 0) { var cc = stack.Pop(); if (NodeIterating || (!NodeIterating && cc.Depth == 0)) { yield return(cc); } if (cc.ElementType == CodeComponentType.Instance) { // 클래스 인경우 Type eType = cc.Element.GetType(); var ignore = eType.GetAttribute <DXIgnoreAttribute>(); foreach (PropertyInfo pi in eType .GetProperties() .Where(pi => pi.HasAttribute <TAttribute>())) { if (ignore != null && ignore.PropertyNames.Contains(pi.Name)) { continue; } var pAttr = pi.GetAttribute <TAttribute>(); var pComponet = new CodeComponent <TAttribute>(pi, pAttr) { Depth = cc.Depth + 1 }; cc.Add(pComponet); stack.Push(pComponet); } } else { var pi = cc.Element as PropertyInfo; // 배열인 경우 if (pi.CanCastingTo <IEnumerable <PObject> >()) { var list = (IEnumerable <PObject>)pi.GetValue(cc.Parent.Element); if (list == null) { continue; } // 스택 처리 순서와 코드 구성 순서를 맞추기위해 뒤집어야함 foreach (var obj in list.Reverse()) { var oAttr = obj.GetAttribute <TAttribute>(); var oComponent = new CodeComponent <TAttribute>(obj, oAttr) { Depth = cc.Depth + 1 }; cc.Add(oComponent); stack.Push(oComponent); } } else if (pi.CanCastingTo <PObject>()) { var obj = pi.GetValue(cc.Parent.Element); if (obj == null) { continue; } var oAttr = obj.GetAttribute <TAttribute>(); var oComponent = new CodeComponent <TAttribute>(obj, oAttr) { Depth = cc.Depth + 1 }; cc.Add(oComponent); stack.Push(oComponent); } } } } } }
public int GetHashCode(CodeComponent <TAttribute> obj) { return(obj.Element.GetHashCode()); }
public bool Equals(CodeComponent <TAttribute> x, CodeComponent <TAttribute> y) { return(x.Element.Equals(y.Element)); }
protected override IEnumerable <string> OnGenerate(IEnumerable <CodeComponent <CSharpCodeMapAttribute> > components) { var items = components.ToArray(); CodeComponent <CSharpCodeMapAttribute> root = items.FirstOrDefault(); // Trigger Hosts CodeComponent <CSharpCodeMapAttribute>[] triggers = items .Where(cc => cc.Depth == 0) .SelectMany(item => item.Children) .Where(item => item.Element is PTrigger) .Distinct(new CodeComponentComparer <CSharpCodeMapAttribute>()) .ToArray(); //// Trigger Hosts //CodeComponent<CSharpCodeMapAttribute>[] triggers = items // .Where(cc => cc.Depth == 0) // .SelectMany(item => item.Children) // .Distinct(new CodeComponentComparer<CSharpCodeMapAttribute>()) // .ToArray(); // Event Handle var eventHandlerBuilder = new StringBuilder(); foreach (var trigger in triggers) { var result = this.Mapper.Build(trigger.Element, trigger.Attribute.MappingCode); string source = result.Source; string callbackName = Mapper.MappingProvider.GetEventCallbackName(trigger.Element as PTrigger); source = source.Replace("{EventCallback}", callbackName); eventHandlerBuilder.AppendLine(source); } yield return(eventHandlerBuilder.ToString()); // Callback foreach (var trigger in triggers) { string callbackSource = GenerateCallback(trigger.Element as PTrigger); string code = ""; if (trigger.HasChildren) { // 지역 변수 컨테이너 var localVariableContainer = new NameContainer(); code = CreateScope(trigger.Children.ToArray(), localVariableContainer, true); } yield return(callbackSource.Replace("{Code}", code)); } // CreateScope (Recursive) string CreateScope(CodeComponent <CSharpCodeMapAttribute>[] scopeComponents, NameContainer localVariableContainer, bool isCodeBlock = false) { var scopeBuilder = new IndentStringBuilder(); var stack = new Stack <CodeComponent <CSharpCodeMapAttribute> >(scopeComponents); if (!isCodeBlock) { scopeBuilder.AppendLine(); scopeBuilder.AppendLine("{"); } while (stack.Count > 0) { var cc = stack.Pop(); var mappingResult = this.Mapper.Build(cc.Element, cc.Attribute.MappingCode); var sourceBuilder = new IndentStringBuilder(mappingResult.Source); if (cc.Element is PBinderHost host) { foreach (DXToken token in mappingResult.Errors) { switch (token.Token) { case "Scope": { if (!token.IsIndexed) { continue; } int index = int.Parse(token.Parameter) - 1; var scopeBinder = host[BindOptions.Output].ElementAt(index) as PBinder; var childScopeComponents = scopeBinder.Items .Select(item => item.Host as PBinderHost) .Distinct() .Select(childHost => new CodeComponent <CSharpCodeMapAttribute>( childHost, childHost.GetAttribute <CSharpCodeMapAttribute>())) .ToArray(); sourceBuilder.Replace( token.OriginalSource, CreateScope(childScopeComponents, localVariableContainer)); break; } case "Line": { if (!token.IsIndexed) { continue; } int index = int.Parse(token.Parameter) - 1; var paramBinder = host[BindOptions.Parameter].ElementAt(index) as PBinder; ProcessBinderValue(sourceBuilder, token, paramBinder); break; } default: break; } } } scopeBuilder.AppendBlock(sourceBuilder.ToString(), 1); scopeBuilder.AppendLine(); } if (!isCodeBlock) { scopeBuilder.AppendLine("}"); } return(scopeBuilder.ToString()); } //string CreateLambda() void ProcessBinderValue(IndentStringBuilder sourceBuilder, DXToken token, PBinder binder) { string valueLine = null; // 직접 입력 if (binder.IsDirectValue) { object value = binder.DirectValue; valueLine = this.Mapper.MappingProvider.GetValueLine(value, true); } // 연결됨 else if (binder.Items.Count == 1) { var paramOutputHost = binder.Items[0].Host; var attr = paramOutputHost.GetAttribute <CSharpCodeMapAttribute>(); if (paramOutputHost is PTrigger) { valueLine = "sender"; } else { valueLine = this.Mapper.Build(paramOutputHost, attr.MappingCode).Source; } } else { // Error } if (valueLine != null) { int idx = sourceBuilder.IndexOf(token.OriginalSource); // 토큰 부분 제거 sourceBuilder.Replace(token.OriginalSource, ""); sourceBuilder.Insert(idx, valueLine); } } }
private XmlElement CreateElement(XmlDocument doc, CodeComponent <WPFAttribute> component) { return(CreateElement(doc, component.Attribute.Name, component)); }
protected override IEnumerable <string> OnGenerate(IEnumerable <CodeComponent <WPFAttribute> > components) { var items = components.ToArray(); CodeComponent <WPFAttribute> root = items.FirstOrDefault(); // 이름이 설정되지 않은경우 생성해줌 ImagePatch(items); NamingPatch(items); NamespacePatch(items); if (root.Element is PPage page) { this.NameContainer[page] = page.GetPageName(); } var doc = new XmlDocument(); XmlElement rootElement = CreateElement(doc, root); rootElement.SetAttribute("xmlns", XMLNS); // 네임스페이스 선언 foreach (var namespaceKv in this.XamlNamespaceContainer) { rootElement.SetAttribute($"xmlns:{namespaceKv.Value}", namespaceKv.Key); } SetXamlName(rootElement, root); var comQueue = new Queue <CodeComponent <WPFAttribute> >(new[] { root }); var xmlQueue = new Queue <XmlElement>(new[] { rootElement }); while (comQueue.Count > 0) { var com = comQueue.Dequeue(); var xml = xmlQueue.Dequeue(); if (com.HasChildren) { var content = com.GetContentComponent(); // property foreach (var child in com.Children .Where(c => c.ElementType == CodeComponentType.Property)) { if (content == child) { continue; } var pi = child.Element as PropertyInfo; //if (pi.IsDefaultDependencyProperty(child.Parent.Element as PObject)) // continue; object value = pi.GetValue(child.Parent.Element); if (pi.CanCastingTo <IEnumerable <PObject> >()) { XmlElement lstXml = CreateElement(doc, $"{child.Parent.Attribute.Name}.{child.Attribute.Name}", child.Parent); xml.AppendChild(lstXml); if (child.HasChildren) { foreach (var item in child.Children?.Reverse()) { XmlElement childXml = CreateElement(doc, item); lstXml.AppendChild(childXml); SetXamlName(childXml, item); comQueue.Enqueue(item); xmlQueue.Enqueue(childXml); } } } else { bool isContinue = false; // Null Reference isContinue |= (value == null); // Auto Size Pass isContinue |= (value is double && double.IsNaN((double)value)); if (!isContinue) { if (child.HasResource) { xml.SetAttribute( child.Attribute.Name, GetResourceName(child.ResourceType.Value, value.ToString())); } else { xml.SetAttribute( child.Attribute.Name, ValueToXamlInline(value)); } } } } // Content if (content != null && content.HasChildren) { var pi = content.Element as PropertyInfo; if (pi.CanCastingTo <IEnumerable <PObject> >()) { foreach (var item in content.Children?.Reverse()) { XmlElement contentXml = CreateElement(doc, item); xml.AppendChild(contentXml); SetXamlName(contentXml, item); comQueue.Enqueue(item); xmlQueue.Enqueue(contentXml); } } else if (pi.CanCastingTo <PObject>()) { var contentItem = content.Children[0]; XmlElement contentXml = CreateElement(doc, contentItem); xml.AppendChild(contentXml); SetXamlName(contentXml, contentItem); comQueue.Enqueue(contentItem); xmlQueue.Enqueue(contentXml); } } } } doc.AppendChild(rootElement); // 인덴트 처리 using (var ms = new MemoryStream()) { using (var writer = new XmlTextWriter(ms, new UTF8Encoding(false))) { writer.Formatting = Formatting.Indented; doc.Save(writer); yield return(Encoding.UTF8.GetString(ms.ToArray())); } } }
private string XamlGenerate(IEnumerable <CodeComponent <XFormsAttribute> > components) { var items = components.ToArray(); CodeComponent <XFormsAttribute> root = items[0]; string pageName = null; if (root.Element is PPage page) { pageName = page.GetPageName(); } // 루트페이지는 항상 이름(파일, 클래스 이름)이 설정되어있어야 함 if (pageName == null) { throw new ArgumentException(); } var doc = new XmlDocument(); var dec = doc.CreateXmlDeclaration("1.0", "utf-8", null); // 노드 XmlElement rootElement = doc.CreateElement(root.Attribute.Name); rootElement.SetAttribute("xmlns", XMLNS); rootElement.SetAttribute("xmlns:x", XMLNSX); rootElement.SetAttribute("xmlns:local", $"clr-namespace:{this.Manifest.RootNamespace}"); rootElement.SetAttribute("Class", XMLNSX, $"{this.Manifest.RootNamespace}.{pageName}"); SetXamlName(rootElement, root); var comQueue = new Queue <CodeComponent <XFormsAttribute> >(new[] { root }); var xmlQueue = new Queue <XmlElement>(new[] { rootElement }); while (comQueue.Count > 0) { var com = comQueue.Dequeue(); var xml = xmlQueue.Dequeue(); if (com.HasChildren) { var content = com.GetContentComponent(); // property foreach (var child in com.Children .Where(c => c.ElementType == CodeComponentType.Property)) { if (content == child) { continue; } var pi = child.Element as PropertyInfo; if (pi.IsDefaultDependencyProperty(child.Parent.Element as PObject)) { continue; } object value = pi.GetValue(child.Parent.Element); if (pi.CanCastingTo <IEnumerable <PObject> >()) { var lstXml = doc.CreateElement( $"{child.Parent.Attribute.Name}.{child.Attribute.Name}"); xml.AppendChild(lstXml); if (child.HasChildren) { foreach (var item in child.Children?.Reverse()) { var childXml = doc.CreateElement(item.Attribute.Name); lstXml.AppendChild(childXml); SetXamlName(childXml, item); comQueue.Enqueue(item); xmlQueue.Enqueue(childXml); } } } else { bool isContinue = false; // Null Reference isContinue |= (value == null); // Auto Size Pass isContinue |= (value is double && double.IsNaN((double)value)); if (!isContinue) { xml.SetAttribute( child.Attribute.Name, ValueToXamlInline(value)); } } } // Content if (content != null && content.HasChildren) { var pi = content.Element as PropertyInfo; if (pi.CanCastingTo <IEnumerable <PObject> >()) { foreach (var item in content.Children?.Reverse()) { var contentXml = doc.CreateElement(item.Attribute.Name); xml.AppendChild(contentXml); SetXamlName(contentXml, item); comQueue.Enqueue(item); xmlQueue.Enqueue(contentXml); } } else if (pi.CanCastingTo <PObject>()) { var contentItem = content.Children[0]; var contentXml = doc.CreateElement(contentItem.Attribute.Name); xml.AppendChild(contentXml); SetXamlName(contentXml, contentItem); comQueue.Enqueue(contentItem); xmlQueue.Enqueue(contentXml); } } } } doc.AppendChild(dec); doc.AppendChild(rootElement); // 인덴트 처리 using (var ms = new MemoryStream()) { using (var writer = new XmlTextWriter(ms, new UTF8Encoding(false))) { writer.Formatting = Formatting.Indented; doc.Save(writer); return(Encoding.UTF8.GetString(ms.ToArray())); } } }
public override IEnumerable <CodeComponent <TAttribute> > GetComponents <TAttribute>() { if (Items != null) { foreach (PObject item in Items .SelectMany(host => host.Items.GetExpressions()) .Select(e => e.Output.Host) .Distinct()) { if (!item.HasAttribute <TAttribute>()) { continue; } var attr = item.GetAttribute <TAttribute>(); var component = new CodeComponent <TAttribute>(item, attr); var stack = new Stack <CodeComponent <TAttribute> >(new[] { component }); component.ElementType = CodeComponentType.Node; while (stack.Count > 0) { var cc = stack.Pop(); //if (NodeIterating || (!NodeIterating && cc.Depth == 0)) // yield return cc; if (cc.ElementType == CodeComponentType.Node) { var host = cc.Element as PBinderHost; var zeroNodes = new List <PBinderHost>(); var childStack = new Stack <PBinderHost>(new[] { host }); // 호스트와 연결된 모든 노드를 BFS알고리즘을 사용하여 가져오고 // 생성된 Output Binder의 갯수가 1개인 것만 노드로 인정함 // 갯수가 2개이상인 노드에서 멈춤 (2개이상은 스코프가 분기된다고 가정) while (childStack.Count > 0) { PBinderHost child = childStack.Pop(); foreach (PBinderHost childNode in BinderHelper.FindHostNodes(child, BindOptions.Output, 0)) { if (childNode[BindOptions.Output].Count() == 1 && childNode is PTrigger == false) { childStack.Push(childNode); } zeroNodes.Add(childNode); } } foreach (PBinderHost zeroNode in zeroNodes) { var childComponent = new CodeComponent <TAttribute>( zeroNode, zeroNode.GetAttribute <TAttribute>()) { Depth = cc.Depth + 1, ElementType = CodeComponentType.Node }; cc.Add(childComponent); if (zeroNode[BindOptions.Output].Count() > 1 || zeroNode is PTrigger) { stack.Push(childComponent); } } } } yield return(component); } } }