From: Fang Xiaohui Date: Mon, 11 Apr 2022 05:19:36 +0000 (+0800) Subject: [Xaml] Support import other xaml as the source of resource dictionary X-Git-Tag: submit/tizen_6.5/20220412.151247~1^2~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bd5c699d69db44c93d8812ea9f91a9df2db4e639;p=platform%2Fcore%2Fcsapi%2Ftizenfx.git [Xaml] Support import other xaml as the source of resource dictionary --- diff --git a/pkg/Tizen.NET.API9/xamlbuild/Tizen.NUI.XamlBuild.dll b/pkg/Tizen.NET.API9/xamlbuild/Tizen.NUI.XamlBuild.dll index e0971a54c..36fb44100 100644 Binary files a/pkg/Tizen.NET.API9/xamlbuild/Tizen.NUI.XamlBuild.dll and b/pkg/Tizen.NET.API9/xamlbuild/Tizen.NUI.XamlBuild.dll differ diff --git a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXaml/EXamlCreateObject/EXamlCreateResourceDictionary.cs b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXaml/EXamlCreateObject/EXamlCreateResourceDictionary.cs new file mode 100755 index 000000000..60ec6fb3e --- /dev/null +++ b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXaml/EXamlCreateObject/EXamlCreateResourceDictionary.cs @@ -0,0 +1,68 @@ +/* + * Copyright(c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +using Mono.Cecil; +using System; +using System.Collections.Generic; +using System.Text; +using Tizen.NUI.EXaml.Build.Tasks; + +namespace Tizen.NUI.EXaml +{ + internal class EXamlCreateResourceDictionary : EXamlCreateObject + { + public EXamlCreateResourceDictionary(EXamlContext context, TypeReference type, string content = null) : base(context, null, type) + { + if (null != content) + { + Content = content; + } + } + + private string content; + public string Content + { + get + { + return content; + } + set + { + content = value; + indexRangeOfContent = eXamlContext.GetLongStringIndexs(content); + } + } + + private (int, int) indexRangeOfContent; + + internal override string Write() + { + if (false == IsValid) + { + return ""; + } + + string ret = String.Format("({0} ({1} {2} {3}))\n", + eXamlContext.GetValueString((int)EXamlOperationType.CreateResourceDictionary), + eXamlContext.GetValueString(eXamlContext.GetTypeIndex(Type)), + eXamlContext.GetValueString(indexRangeOfContent.Item1), + eXamlContext.GetValueString(indexRangeOfContent.Item2)); + + return ret; + } + } +} + diff --git a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlContext.cs b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlContext.cs index 913e95a21..a2c8059a1 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlContext.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlContext.cs @@ -26,7 +26,7 @@ namespace Tizen.NUI.EXaml.Build.Tasks { internal class EXamlContext { - public EXamlContext(TypeDefinition type, ModuleDefinition module, FieldDefinition parentContextValues = null) + public EXamlContext(TypeDefinition type, ModuleDefinition module, string embeddedResourceNameSpace, FieldDefinition parentContextValues = null) { Values = new Dictionary(); Variables = new Dictionary(); @@ -35,6 +35,7 @@ namespace Tizen.NUI.EXaml.Build.Tasks ParentContextValues = parentContextValues; Type = type; Module = module; + EmbeddedResourceNameSpace = embeddedResourceNameSpace; } public Dictionary Values { get; private set; } @@ -55,6 +56,8 @@ namespace Tizen.NUI.EXaml.Build.Tasks public ModuleDefinition Module { get; private set; } + public string EmbeddedResourceNameSpace { get; } + public List eXamlOperations = new List(); private string GetAssemblyName(AssemblyDefinition assembly) diff --git a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlCreateObjectVisitor.cs b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlCreateObjectVisitor.cs index add12fcf5..88c5b72e0 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlCreateObjectVisitor.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlCreateObjectVisitor.cs @@ -27,6 +27,7 @@ using static Mono.Cecil.Cil.Instruction; using static Mono.Cecil.Cil.OpCodes; using Tizen.NUI.Xaml.Build.Tasks; using ArrayExtension = Tizen.NUI.Xaml.Build.Tasks.ArrayExtension; +using Tizen.NUI.Binding; namespace Tizen.NUI.EXaml.Build.Tasks { @@ -290,7 +291,7 @@ namespace Tizen.NUI.EXaml.Build.Tasks var accordingType = this.GetType().Assembly.GetType(typeref.FullName); - if (null != accordingType && accordingType != typeof(Binding.Setter)) + if (null != accordingType && accordingType != typeof(Binding.Setter) && accordingType != typeof(ResourceDictionary)) { Context.Values[node] = new EXamlCreateObject(Context, Activator.CreateInstance(accordingType), typeref); } diff --git a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlSetPropertiesVisitor.cs b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlSetPropertiesVisitor.cs index 7536020a6..ac2ee2f1e 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlSetPropertiesVisitor.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/EXamlSetPropertiesVisitor.cs @@ -924,6 +924,10 @@ namespace Tizen.NUI.EXaml.Build.Tasks var fieldRef = bindableProperty.DeclaringType.ResolveCached().Fields.FirstOrDefault(a => a.FullName == bindableProperty.FullName); context.Values[node] = new EXamlCreateObject(context, bindableProperty.DeclaringType, fieldRef, null); } + else if ("Tizen.NUI.Binding.ResourceDictionary" == propertyType.FullName) + { + context.Values[node] = GetResourceDictionaryByXaml(parent, node, context, iXmlLineInfo); + } else { var converterType = valueNode.GetConverterType(new ICustomAttributeProvider[] { property, propertyType.ResolveCached() }); @@ -1146,11 +1150,10 @@ namespace Tizen.NUI.EXaml.Build.Tasks return false; } - static void SetDataTemplate(ElementNode parentNode, ElementNode rootnode, EXamlContext parentContext, - IXmlLineInfo xmlLineInfo) + static void SetDataTemplate(ElementNode parentNode, ElementNode rootnode, EXamlContext parentContext, IXmlLineInfo xmlLineInfo) { var typeref = parentContext.Module.ImportReference(rootnode.XmlType.GetTypeReference(XmlTypeExtensions.ModeOfGetType.Both, parentContext.Module, rootnode)); - var visitorContext = new EXamlContext(typeref.ResolveCached(), typeref.Module); + var visitorContext = new EXamlContext(typeref.ResolveCached(), typeref.Module, parentContext.EmbeddedResourceNameSpace); rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); rootnode.Accept(new EXamlExpandMarkupsVisitor(visitorContext), null); @@ -1172,6 +1175,77 @@ namespace Tizen.NUI.EXaml.Build.Tasks } } + static EXamlCreateResourceDictionary GetResourceDictionaryByXaml(EXamlCreateObject parentObject, INode nodeOfXaml, EXamlContext parentContext, IXmlLineInfo xmlLineInfo) + { + var module = parentContext.Module; + + string xamlName = ""; + + if (nodeOfXaml is ValueNode valueNode) + { + xamlName = valueNode.Value as string; + } + + EmbeddedResource matchedResource = null; + + foreach (var resource in module.Resources.OfType()) + { + if (resource.Name.StartsWith(parentContext.EmbeddedResourceNameSpace) && resource.Name.EndsWith(xamlName)) + { + matchedResource = resource; + break; + } + } + + if (null == matchedResource) + { + foreach (var resource in module.Resources.OfType()) + { + if (resource.Name.EndsWith(xamlName)) + { + matchedResource = resource; + break; + } + } + } + + if (null != matchedResource) + { + string classname; + + if (matchedResource.IsResourceDictionaryXaml(module, out classname)) + { + int lastIndex = classname.LastIndexOf('.'); + var realClassName = classname.Substring(lastIndex + 1); + var typeref = XmlTypeExtensions.GetTypeReference(realClassName, module, nodeOfXaml as BaseNode, XmlTypeExtensions.ModeOfGetType.Both); + + var visitorContext = new EXamlContext(typeref.ResolveCached(), typeref.Module, parentContext.EmbeddedResourceNameSpace); + var rootnode = XamlTask.ParseXaml(matchedResource.GetResourceStream(), typeref); + + var rootInstance = new EXamlCreateObject(visitorContext, null, typeref); + visitorContext.Values[rootnode] = rootInstance; + + rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); + rootnode.Accept(new EXamlExpandMarkupsVisitor(visitorContext), null); + rootnode.Accept(new PruneIgnoredNodesVisitor(), null); + rootnode.Accept(new EXamlCreateObjectVisitor(visitorContext), null); + rootnode.Accept(new EXamlSetNamescopesAndRegisterNamesVisitor(visitorContext), null); + rootnode.Accept(new EXamlSetFieldVisitor(visitorContext), null); + rootnode.Accept(new EXamlSetResourcesVisitor(visitorContext), null); + rootnode.Accept(new EXamlSetPropertiesVisitor(visitorContext, true), null); + + foreach (var pair in visitorContext.resourceDictionary) + { + parentContext.resourceDictionary.Add(pair.Key, pair.Value); + } + + return new EXamlCreateResourceDictionary(parentContext, typeref, visitorContext.GenerateEXamlString()); + } + } + + return null; + } + bool TrySetRuntimeName(XmlName propertyName, EXamlCreateObject variableDefinition, ValueNode node) { if (null == variableDefinition) diff --git a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/Utility/EXamlOperationType.cs b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/Utility/EXamlOperationType.cs index 60be87399..eaeb5676d 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/Utility/EXamlOperationType.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/EXamlBuild/Utility/EXamlOperationType.cs @@ -48,6 +48,7 @@ namespace Tizen.NUI.EXaml RegisterXName, GetLongString, CreateDPObject, + CreateResourceDictionary, MAX } } diff --git a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/CompiledConverters/RDSourceTypeConverter.cs b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/CompiledConverters/RDSourceTypeConverter.cs index 8851b75dd..baac8ff51 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/CompiledConverters/RDSourceTypeConverter.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/CompiledConverters/RDSourceTypeConverter.cs @@ -26,6 +26,7 @@ using static Mono.Cecil.Cil.OpCodes; using Tizen.NUI.Xaml.Build.Tasks; using Tizen.NUI.Xaml; using Tizen.NUI.Binding; +using System.Linq; namespace Tizen.NUI.Xaml.Core.XamlC { @@ -33,55 +34,89 @@ namespace Tizen.NUI.Xaml.Core.XamlC { public IEnumerable ConvertFromString(string value, ILContext context, BaseNode node) { - var module = context.Body.Method.Module; - var body = context.Body; - - INode rootNode = node; - while (!(rootNode is ILRootNode)) - rootNode = rootNode.Parent; - - var rdNode = node.Parent as IElementNode; - - var rootTargetPath = XamlTask.GetPathForType(module, ((ILRootNode)rootNode).TypeReference); - var uri = new Uri(value, UriKind.Relative); - - var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath); - - //fail early - var resourceId = XamlTask.GetResourceIdForPath(module, resourcePath); - if (resourceId == null) - throw new XamlParseException($"Resource '{value}' not found.", node); - - - //abuse the converter, produce some side effect, but leave the stack untouched - //public void SetAndLoadSource(Uri value, string resourceID, Assembly assembly, System.Xml.IXmlLineInfo lineInfo) - yield return Create(Ldloc, context.Variables[rdNode]); //the resourcedictionary - foreach (var instruction in (new UriTypeConverter()).ConvertFromString(value, context, node)) - yield return instruction; //the Uri - - //keep the Uri for later - yield return Create(Dup); - var uriVarDef = new VariableDefinition(module.ImportReference(("System", "System", "Uri"))); - body.Variables.Add(uriVarDef); - yield return Create(Stloc, uriVarDef); - yield return Create(Ldstr, resourcePath); //resourcePath - yield return Create(Ldtoken, module.ImportReference(((ILRootNode)rootNode).TypeReference)); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System", "Type"), methodName: "GetTypeFromHandle", parameterTypes: new[] { ("mscorlib", "System", "RuntimeTypeHandle") }, isStatic: true)); - yield return Create(Call, module.ImportMethodReference(("mscorlib", "System.Reflection", "IntrospectionExtensions"), methodName: "GetTypeInfo", parameterTypes: new[] { ("mscorlib", "System", "Type") }, isStatic: true)); - yield return Create(Callvirt, module.ImportPropertyGetterReference(("mscorlib", "System.Reflection", "TypeInfo"), propertyName: "Assembly", flatten: true)); - - foreach (var instruction in node.PushXmlLineInfo(context)) - yield return instruction; //lineinfo - yield return Create(Callvirt, module.ImportMethodReference((XamlTask.bindingAssemblyName, XamlTask.bindingNameSpace, "ResourceDictionary"), - methodName: "SetAndLoadSource", - parameterTypes: new[] { ("System", "System", "Uri"), ("mscorlib", "System", "String"), ("mscorlib", "System.Reflection", "Assembly"), ("System.Xml.ReaderWriter", "System.Xml", "IXmlLineInfo") })); - //ldloc the stored uri as return value - yield return Create(Ldloc, uriVarDef); + var module = context.Module; + + EmbeddedResource matchedResource = null; + + foreach (var resource in module.Resources.OfType()) + { + if (resource.Name.StartsWith(context.EmbeddedResourceNameSpace) && resource.Name.EndsWith(value)) + { + matchedResource = resource; + break; + } + } + + if (null == matchedResource) + { + foreach (var resource in module.Resources.OfType()) + { + if (resource.Name.EndsWith(value)) + { + matchedResource = resource; + break; + } + } + } + + if (null != matchedResource) + { + string classname; + if (matchedResource.IsResourceDictionaryXaml(module, out classname)) + { + int lastIndex = classname.LastIndexOf('.'); + var realClassName = classname.Substring(lastIndex + 1); + var typeref = XmlTypeExtensions.GetTypeReference(realClassName, module, node, XmlTypeExtensions.ModeOfGetType.Both); + + var typeName = matchedResource.Name.Replace('.', '_'); + var typeDefOfGetResource = module.Types.FirstOrDefault(type => type.FullName == "GetResource." + typeName); + if (null != typeDefOfGetResource) + { + module.Types.Remove(typeDefOfGetResource); + typeDefOfGetResource = null; + } + + if (null == typeDefOfGetResource) + { + typeDefOfGetResource = new TypeDefinition("GetResource", typeName, TypeAttributes.NotPublic); + typeDefOfGetResource.BaseType = typeref; + module.Types.Add(typeDefOfGetResource); + + typeDefOfGetResource.AddDefaultConstructor(typeref); + } + + var methodName = "GetResource"; + var methodOfGetResource = typeDefOfGetResource.Methods.FirstOrDefault(m => m.Name == methodName); + + if (null == methodOfGetResource) + { + methodOfGetResource = new MethodDefinition(methodName, MethodAttributes.Public, typeref); + typeDefOfGetResource.Methods.Add(methodOfGetResource); + } + + var constructor = typeDefOfGetResource.Methods.FirstOrDefault(m => m.IsConstructor); + + if (null != constructor) + { + constructor.Body.Instructions.Insert(constructor.Body.Instructions.Count - 1, Instruction.Create(OpCodes.Ldarg_0)); + constructor.Body.Instructions.Insert(constructor.Body.Instructions.Count - 1, Instruction.Create(OpCodes.Call, methodOfGetResource)); + constructor.Body.Instructions.Insert(constructor.Body.Instructions.Count - 1, Instruction.Create(OpCodes.Pop)); + } + + var rootnode = XamlTask.ParseXaml(matchedResource.GetResourceStream(), typeref); + + Exception exception; + TryCoreCompile(methodOfGetResource, rootnode, context.EmbeddedResourceNameSpace, out exception); + + yield return Create(Newobj, constructor); + } + } } internal static string GetPathForType(ModuleDefinition module, TypeReference type) { - foreach (var ca in type.Module.GetCustomAttributes()) { + foreach (var ca in type.Module.GetCustomAttributes()) + { if (!TypeRefComparer.Default.Equals(ca.AttributeType, module.ImportReference((XamlTask.xamlAssemblyName, XamlTask.xamlNameSpace, "XamlResourceIdAttribute")))) continue; if (!TypeRefComparer.Default.Equals(ca.ConstructorArguments[2].Value as TypeReference, type)) @@ -90,6 +125,57 @@ namespace Tizen.NUI.Xaml.Core.XamlC } return null; } + + private bool TryCoreCompile(MethodDefinition initComp, ILRootNode rootnode, string resourceName, out Exception exception) + { + try + { + var body = new MethodBody(initComp); + var module = body.Method.Module; + var type = initComp.DeclaringType; + + body.InitLocals = true; + var il = body.GetILProcessor(); + il.Emit(OpCodes.Ldarg_0); + var resourcePath = GetPathForType(module, type); + + il.Emit(Nop); + + List insOfAddEvent = new List(); + + var visitorContext = new ILContext(il, body, insOfAddEvent, module, resourceName); + + rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); + rootnode.Accept(new Tizen.NUI.Xaml.Build.Tasks.ExpandMarkupsVisitor(visitorContext), null); + rootnode.Accept(new PruneIgnoredNodesVisitor(), null); + rootnode.Accept(new CreateObjectVisitor(visitorContext), null); + + rootnode.Accept(new SetNamescopesAndRegisterNamesVisitor(visitorContext), null); + rootnode.Accept(new SetFieldVisitor(visitorContext), null); + rootnode.Accept(new SetResourcesVisitor(visitorContext), null); + rootnode.Accept(new SetPropertiesVisitor(visitorContext, true), null); + + il.Emit(Ret); + initComp.Body = body; + exception = null; + return true; + } + catch (Exception e) + { + XamlParseException xamlParseException = e as XamlParseException; + if (null != xamlParseException) + { + XamlParseException ret = new XamlParseException(xamlParseException.Message, xamlParseException.XmlInfo, xamlParseException.InnerException); + exception = ret; + } + else + { + exception = e; + } + + return false; + } + } } } - + diff --git a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/ILContext.cs b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/ILContext.cs index eae1d25c2..474ad8cb2 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/ILContext.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/ILContext.cs @@ -26,7 +26,7 @@ namespace Tizen.NUI.Xaml.Build.Tasks { class ILContext { - public ILContext(ILProcessor il, MethodBody body, List insOfAddEvent, ModuleDefinition module, FieldDefinition parentContextValues = null) + public ILContext(ILProcessor il, MethodBody body, List insOfAddEvent, ModuleDefinition module, string embeddedResourceNameSpace, FieldDefinition parentContextValues = null) { IL = il; Body = body; @@ -35,6 +35,7 @@ namespace Tizen.NUI.Xaml.Build.Tasks Variables = new Dictionary(); Scopes = new Dictionary>>(); TypeExtensions = new Dictionary(); + EmbeddedResourceNameSpace = embeddedResourceNameSpace; ParentContextValues = parentContextValues; Module = module; } @@ -47,6 +48,8 @@ namespace Tizen.NUI.Xaml.Build.Tasks public Dictionary TypeExtensions { get; } + public string EmbeddedResourceNameSpace { get; } + public FieldDefinition ParentContextValues { get; private set; } public object Root { get; set; } //FieldDefinition or VariableDefinition diff --git a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/SetPropertiesVisitor.cs b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/SetPropertiesVisitor.cs index 15863d8ac..5b1742661 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/SetPropertiesVisitor.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/SetPropertiesVisitor.cs @@ -1482,7 +1482,7 @@ namespace Tizen.NUI.Xaml.Build.Tasks //Fill the loadTemplate Body var templateIl = loadTemplate.Body.GetILProcessor(); templateIl.Emit(OpCodes.Nop); - var templateContext = new ILContext(templateIl, loadTemplate.Body, null, module, parentValues) + var templateContext = new ILContext(templateIl, loadTemplate.Body, null, module, parentContext.EmbeddedResourceNameSpace, parentValues) { Root = root }; diff --git a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/XamlCTask.cs b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/XamlCTask.cs index 8827aff0d..32ae82592 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/XamlCTask.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/XamlCTask.cs @@ -380,6 +380,17 @@ namespace Tizen.NUI.Xaml.Build.Tasks return success; } + private string GetNameSpaceOfResource(EmbeddedResource resource) + { + var index = resource.Name.LastIndexOf('.'); + var resourceNameWithoutSubfix = resource.Name.Substring(0, index); + + index = resourceNameWithoutSubfix.LastIndexOf('.'); + var nameSpace = resourceNameWithoutSubfix.Substring(0, index); + + return nameSpace; + } + bool DoInjection(TypeDefinition typeDef, EmbeddedResource resource, out IList thrownExceptions) { thrownExceptions = null; @@ -431,7 +442,9 @@ namespace Tizen.NUI.Xaml.Build.Tasks LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Replacing {0}.InitializeComponent ()"); Exception e; - if (!TryCoreCompile(initComp, rootnode, out e)) + + var embeddedResourceNameSpace = GetNameSpaceOfResource(resource); + if (!TryCoreCompile(initComp, rootnode, embeddedResourceNameSpace, out e)) { LoggingHelper.LogMessage(Low, $"{new string(' ', 8)}failed."); (thrownExceptions = thrownExceptions ?? new List()).Add(e); @@ -494,7 +507,8 @@ namespace Tizen.NUI.Xaml.Build.Tasks LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Replacing {0}.InitializeComponent ()"); Exception e; - var visitorContext = new EXamlContext(typeDef, typeDef.Module); + var embeddedResourceNameSpace = GetNameSpaceOfResource(resource); + var visitorContext = new EXamlContext(typeDef, typeDef.Module, embeddedResourceNameSpace); if (!TryCoreCompile(rootnode, visitorContext, out e)) { @@ -567,7 +581,7 @@ namespace Tizen.NUI.Xaml.Build.Tasks LoggingHelper.LogMessage(Low, $"{new string(' ', 6)}Replacing {0}.InitializeComponent ()"); Exception e; - var visitorContext = new EXamlContext(typeDef, module); + var visitorContext = new EXamlContext(typeDef, module, null); if (!TryCoreCompile(rootnode, visitorContext, out e)) { @@ -621,7 +635,7 @@ namespace Tizen.NUI.Xaml.Build.Tasks return true; } - bool TryCoreCompile(MethodDefinition initComp, ILRootNode rootnode, out Exception exception) + bool TryCoreCompile(MethodDefinition initComp, ILRootNode rootnode, string embeddedResourceNameSpace, out Exception exception) { try { @@ -646,7 +660,7 @@ namespace Tizen.NUI.Xaml.Build.Tasks List insOfAddEvent = new List(); - var visitorContext = new ILContext(il, body, insOfAddEvent, module); + var visitorContext = new ILContext(il, body, insOfAddEvent, module, embeddedResourceNameSpace); rootnode.Accept(new XamlNodeVisitor((node, parent) => node.Parent = parent), null); rootnode.Accept(new ExpandMarkupsVisitor(visitorContext), null); diff --git a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/XamlTask.cs b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/XamlTask.cs index 7c9498b3a..123ed60eb 100755 --- a/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/XamlTask.cs +++ b/src/Tizen.NUI.XamlBuild/src/public/XamlBuild/XamlTask.cs @@ -124,6 +124,42 @@ namespace Tizen.NUI.Xaml.Build.Tasks public static class CecilExtensions { + public static bool IsResourceDictionaryXaml(this EmbeddedResource resource, ModuleDefinition module, out string classname) + { + classname = null; + + if (!resource.Name.EndsWith(".xaml", StringComparison.InvariantCulture)) + return false; + + using (var resourceStream = resource.GetResourceStream()) + { + var xmlDoc = new XmlDocument(); + xmlDoc.Load(resourceStream); + + var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable); + + var root = xmlDoc.SelectSingleNode("/*", nsmgr); + if (root == null) + return false; + + var rootClass = root.Attributes["Class", XamlParser.X2006Uri] ?? + root.Attributes["Class", XamlParser.X2009Uri]; + if (rootClass != null) + { + classname = rootClass.Value; + return true; + } + + if ("ResourceDictionary" == root.Name) + { + classname = "Tizen.NUI.Binding.ResourceDictionary"; + return true; + } + + return false; + } + } + public static bool IsXaml(this EmbeddedResource resource, ModuleDefinition module, out string classname) { classname = null; diff --git a/src/Tizen.NUI/src/internal/EXaml/Action/RootAction.cs b/src/Tizen.NUI/src/internal/EXaml/Action/RootAction.cs index 30051cff7..3294a1b10 100755 --- a/src/Tizen.NUI/src/internal/EXaml/Action/RootAction.cs +++ b/src/Tizen.NUI/src/internal/EXaml/Action/RootAction.cs @@ -238,6 +238,12 @@ namespace Tizen.NUI.EXaml var operation = new CreateDPObject(globalDataList, opInfo); globalDataList.Operations.Add(operation); }; + + createOperations[(int)EXamlOperationType.CreateResourceDictionary] = (GlobalDataList globalDataList, List opInfo) => + { + var operation = new CreateResourceDictionary(globalDataList, opInfo); + globalDataList.Operations.Add(operation); + }; } } } diff --git a/src/Tizen.NUI/src/internal/EXaml/Operation/CreateResourceDictionary.cs b/src/Tizen.NUI/src/internal/EXaml/Operation/CreateResourceDictionary.cs new file mode 100755 index 000000000..19df2f953 --- /dev/null +++ b/src/Tizen.NUI/src/internal/EXaml/Operation/CreateResourceDictionary.cs @@ -0,0 +1,51 @@ +/* + * Copyright(c) 2022 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +using System; +using System.Collections.Generic; +using System.Text; +using Tizen.NUI.Binding; + +namespace Tizen.NUI.EXaml +{ + class CreateResourceDictionary : Operation + { + public CreateResourceDictionary(GlobalDataList globalDataList, List operationInfo) + { + typeIndex = (int)operationInfo[0]; + indexRangeOfContent = ((int)operationInfo[1], (int)operationInfo[2]); + this.globalDataList = globalDataList; + } + + private GlobalDataList globalDataList; + private int typeIndex; + private (int, int) indexRangeOfContent; + + public void Do() + { + var content = globalDataList.LongStrings.Substring(indexRangeOfContent.Item1, indexRangeOfContent.Item2 - indexRangeOfContent.Item1 + 1); + var resourceDictionary = EXamlExtensions.CreateObjectFromEXaml(content) as ResourceDictionary; + + globalDataList.GatheredInstances.Add(resourceDictionary); + + if (null == globalDataList.Root) + { + globalDataList.Root = resourceDictionary; + } + } + } +} diff --git a/src/Tizen.NUI/src/internal/EXaml/Utility/EXamlOperationType.cs b/src/Tizen.NUI/src/internal/EXaml/Utility/EXamlOperationType.cs index 4e5c59878..1956c9c1e 100755 --- a/src/Tizen.NUI/src/internal/EXaml/Utility/EXamlOperationType.cs +++ b/src/Tizen.NUI/src/internal/EXaml/Utility/EXamlOperationType.cs @@ -48,6 +48,7 @@ namespace Tizen.NUI.EXaml RegisterXName, GetLongString, CreateDPObject, + CreateResourceDictionary, MAX } }