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 = 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)));
public IEnumerable <Instruction> ConvertFromString(string value, ILContext context, BaseNode node) { var module = context.Module; EmbeddedResource matchedResource = null; foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { if (resource.Name.StartsWith(context.EmbeddedResourceNameSpace) && resource.Name.EndsWith(value)) { matchedResource = resource; break; } } if (null == matchedResource) { foreach (var resource in module.Resources.OfType <EmbeddedResource>()) { 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)); } } }