public IEnumerable <Instruction> 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 = XamlCTask.GetPathForType(module, ((ILRootNode)rootNode).TypeReference); var uri = new Uri(value, UriKind.Relative); var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath); //fail early var resourceId = XamlCTask.GetResourceIdForPath(module, resourcePath); if (resourceId == null) { throw new BuildException(BuildExceptionCode.ResourceMissing, node, null, value); } var resourceDictionaryType = ("Xamarin.Forms.Core", "Xamarin.Forms", "ResourceDictionary"); //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) foreach (var instruction in context.Variables[rdNode].LoadAs(module.GetTypeDefinition(resourceDictionaryType), module)) { yield return(instruction); } 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)));
public IEnumerable <Instruction> 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 = XamlCTask.GetPathForType(module, ((ILRootNode)rootNode).TypeReference); var uri = new Uri(value, UriKind.Relative); var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath); //fail early var resourceId = XamlCTask.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", paramCount: 1, predicate: md => md.IsStatic))); yield return(Create(Call, module.ImportMethodReference(("mscorlib", "System.Reflection", "IntrospectionExtensions"), methodName: "GetTypeInfo", paramCount: 1, predicate: md => md.IsStatic))); 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(("Xamarin.Forms.Core", "Xamarin.Forms", "ResourceDictionary"), methodName: "SetAndLoadSource", paramCount: 4))); //ldloc the stored uri as return value yield return(Create(Ldloc, uriVarDef)); }
public IEnumerable <Instruction> ConvertFromString(string value, ILContext context, BaseNode node) { var currentModule = 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 = XamlCTask.GetPathForType(currentModule, ((ILRootNode)rootNode).TypeReference); var module = currentModule; string asmName = null; if (value.Contains(";assembly=")) { var parts = value.Split(new[] { ";assembly=" }, StringSplitOptions.RemoveEmptyEntries); value = parts[0]; asmName = parts[1]; if (currentModule.Assembly.Name.Name != asmName) { var ar = currentModule.AssemblyReferences.FirstOrDefault(ar => ar.Name == asmName); if (ar == null) { throw new BuildException(BuildExceptionCode.ResourceMissing, node, null, value); } module = currentModule.AssemblyResolver.Resolve(ar).MainModule; } } var uri = new Uri(value, UriKind.Relative); var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath); //fail early var resourceId = XamlCTask.GetResourceIdForPath(module, resourcePath); if (resourceId == null) { throw new BuildException(BuildExceptionCode.ResourceMissing, node, null, value); } var resourceDictionaryType = ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls", "ResourceDictionary"); //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) foreach (var instruction in context.Variables[rdNode].LoadAs(currentModule.GetTypeDefinition(resourceDictionaryType), currentModule)) { yield return(instruction); } //reappend assembly= in all cases, see other RD converter if (!string.IsNullOrEmpty(asmName)) { value = $"{value};assembly={asmName}"; } else { value = $"{value};assembly={((ILRootNode)rootNode).TypeReference.Module.Assembly.Name.Name}"; } 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(currentModule.ImportReference(("System", "System", "Uri"))); body.Variables.Add(uriVarDef); yield return(Create(Stloc, uriVarDef)); yield return(Create(Ldstr, resourcePath)); //resourcePath if (!string.IsNullOrEmpty(asmName)) { yield return(Create(Ldstr, asmName)); yield return(Create(Call, currentModule.ImportMethodReference(("mscorlib", "System.Reflection", "Assembly"), methodName: "Load", parameterTypes: new[] { ("mscorlib", "System", "String") }, isStatic: true)));
public IEnumerable <Instruction> 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 = XamlCTask.GetPathForType(module, ((ILRootNode)rootNode).TypeReference); var uri = new Uri(value, UriKind.Relative); var resourcePath = ResourceDictionary.RDSourceTypeConverter.GetResourcePath(uri, rootTargetPath); //fail early var resourceId = XamlCTask.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(typeof(Uri))); body.Variables.Add(uriVarDef); yield return(Create(Stloc, uriVarDef)); yield return(Create(Ldstr, resourcePath)); //resourcePath var getTypeFromHandle = module.ImportReference(typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) })); var getTypeInfo = module.ImportReference(typeof(System.Reflection.IntrospectionExtensions).GetMethod("GetTypeInfo", new Type[] { typeof(Type) })); var getAssembly = module.ImportReference(typeof(System.Reflection.TypeInfo).GetProperty("Assembly").GetMethod); yield return(Create(Ldtoken, module.ImportReference(((ILRootNode)rootNode).TypeReference))); yield return(Create(Call, module.ImportReference(getTypeFromHandle))); yield return(Create(Call, module.ImportReference(getTypeInfo))); yield return(Create(Callvirt, module.ImportReference(getAssembly))); //assembly foreach (var instruction in node.PushXmlLineInfo(context)) { yield return(instruction); //lineinfo } var setAndLoadSource = module.ImportReference(typeof(ResourceDictionary).GetMethod("SetAndLoadSource")); yield return(Create(Callvirt, module.ImportReference(setAndLoadSource))); //ldloc the stored uri as return value yield return(Create(Ldloc, uriVarDef)); }