public static Metadata ConvertMetadata(IMetadataReaderSession provider) { var types = new Dictionary <string, MetadataType>(); var typeDefs = new Dictionary <MetadataType, ITypeInformation>(); var metadata = new Metadata(); var resourceUrls = new List <string>(); var avaresValues = new List <AvaresInfo>(); var ignoredResExt = new[] { ".resources", ".rd.xml" }; bool skipRes(string res) => ignoredResExt.Any(r => res.EndsWith(r, StringComparison.OrdinalIgnoreCase)); PreProcessTypes(types, metadata); foreach (var asm in provider.Assemblies) { var aliases = new Dictionary <string, string[]>(); ProcessWellKnownAliases(asm, aliases); ProcessCustomAttributes(asm, aliases); foreach (var type in asm.Types.Where(x => !x.IsInterface && x.IsPublic)) { var mt = types[type.FullName] = ConvertTypeInfomation(type); typeDefs[mt] = type; metadata.AddType("clr-namespace:" + type.Namespace + ";assembly=" + asm.Name, mt); string[] nsAliases = null; if (aliases.TryGetValue(type.Namespace, out nsAliases)) { foreach (var alias in nsAliases) { metadata.AddType(alias, mt); } } } const string avaresToken = "Build:"; //or "Populate:" should work both ways foreach (var resType in asm.Types.Where(t => t.FullName == "CompiledAvaloniaXaml.!AvaloniaResources" || t.Name == "CompiledAvaloniaXaml.!AvaloniaResources")) { foreach (var res in resType.Methods.Where(m => m.Name.StartsWith(avaresToken))) { var localUrl = res.Name.Replace(avaresToken, ""); var avres = new AvaresInfo { Assembly = asm, LocalUrl = localUrl, GlobalUrl = $"avares://{asm.Name}{localUrl}", ReturnTypeFullName = res.ReturnTypeFullName ?? "" }; avaresValues.Add(avres); } } resourceUrls.AddRange(asm.ManifestResourceNames.Where(r => !skipRes(r)).Select(r => $"resm:{r}?assembly={asm.Name}")); } foreach (var type in types.Values) { ITypeInformation typeDef; typeDefs.TryGetValue(type, out typeDef); var ctors = typeDef?.Methods .Where(m => m.IsPublic && !m.IsStatic && m.Name == ".ctor" && m.Parameters.Count == 1); int level = 0; while (typeDef != null) { foreach (var prop in typeDef.Properties) { if (!prop.HasPublicGetter && !prop.HasPublicSetter) { continue; } var p = new MetadataProperty(prop.Name, types.GetValueOrDefault(prop.TypeFullName), types.GetValueOrDefault(typeDef.FullName), false, prop.IsStatic, prop.HasPublicGetter, prop.HasPublicSetter); type.Properties.Add(p); } //check for attached properties only on top level if (level == 0) { foreach (var methodDef in typeDef.Methods) { if (methodDef.Name.StartsWith("Set") && methodDef.IsStatic && methodDef.IsPublic && methodDef.Parameters.Count == 2) { var name = methodDef.Name.Substring(3); type.Properties.Add(new MetadataProperty(name, types.GetValueOrDefault(methodDef.Parameters[1].TypeFullName), types.GetValueOrDefault(typeDef.FullName), true, false, true, true)); } } } if (typeDef.FullName == "Avalonia.AvaloniaObject") { type.IsAvaloniaObjectType = true; } typeDef = typeDef.GetBaseType(); level++; } type.HasAttachedProperties = type.Properties.Any(p => p.IsAttached); type.HasStaticGetProperties = type.Properties.Any(p => p.IsStatic && p.HasGetter); type.HasSetProperties = type.Properties.Any(p => !p.IsStatic && p.HasSetter); if (ctors?.Any() == true) { bool supportType = ctors.Any(m => m.Parameters[0].TypeFullName == "System.Type"); bool supportObject = ctors.Any(m => m.Parameters[0].TypeFullName == "System.Object" || m.Parameters[0].TypeFullName == "System.String"); if (types.TryGetValue(ctors.First().Parameters[0].TypeFullName, out MetadataType parType) && parType.HasHintValues) { type.SupportCtorArgument = MetadataTypeCtorArgument.HintValues; type.HasHintValues = true; type.HintValues = parType.HintValues; } else if (supportType && supportObject) { type.SupportCtorArgument = MetadataTypeCtorArgument.TypeAndObject; } else if (supportType) { type.SupportCtorArgument = MetadataTypeCtorArgument.Type; } else if (supportObject) { type.SupportCtorArgument = MetadataTypeCtorArgument.Object; } } } PostProcessTypes(types, metadata, resourceUrls, avaresValues); return(metadata); }
public static Metadata ConvertMetadata(IMetadataReaderSession provider) { var types = new Dictionary <string, MetadataType>(); var typeDefs = new Dictionary <MetadataType, ITypeInformation>(); var metadata = new Metadata(); var resourceUrls = new List <string>(); var avaresValues = new List <AvaresInfo>(); var ignoredResExt = new[] { ".resources", ".rd.xml", "!AvaloniaResources" }; bool skipRes(string res) => ignoredResExt.Any(r => res.EndsWith(r, StringComparison.OrdinalIgnoreCase)); PreProcessTypes(types, metadata); foreach (var asm in provider.Assemblies) { var aliases = new Dictionary <string, string[]>(); ProcessWellKnownAliases(asm, aliases); ProcessCustomAttributes(asm, aliases); var asmTypes = asm.Types.ToArray(); foreach (var type in asmTypes.Where(x => !x.IsInterface && x.IsPublic)) { var mt = types[type.FullName] = ConvertTypeInfomation(type); typeDefs[mt] = type; metadata.AddType("clr-namespace:" + type.Namespace + ";assembly=" + asm.Name, mt); string[] nsAliases = null; string usingNamespace = $"using:{type.Namespace}"; if (!aliases.TryGetValue(type.Namespace, out nsAliases)) { nsAliases = new string[] { usingNamespace }; aliases[type.Namespace] = nsAliases; } else if (!nsAliases.Contains(usingNamespace)) { aliases[type.Namespace] = nsAliases.Union(new string[] { usingNamespace }).ToArray(); } foreach (var alias in nsAliases) { metadata.AddType(alias, mt); } } ProcessAvaloniaResources(asm, asmTypes, avaresValues); resourceUrls.AddRange(asm.ManifestResourceNames.Where(r => !skipRes(r)).Select(r => $"resm:{r}?assembly={asm.Name}")); } foreach (var type in types.Values) { ITypeInformation typeDef; typeDefs.TryGetValue(type, out typeDef); var ctors = typeDef?.Methods .Where(m => m.IsPublic && !m.IsStatic && m.Name == ".ctor" && m.Parameters.Count == 1); if (typeDef?.IsEnum ?? false) { foreach (var value in typeDef.EnumValues) { var p = new MetadataProperty(value, type, type, false, true, true, false); type.Properties.Add(p); } } int level = 0; while (typeDef != null) { var currentType = types.GetValueOrDefault(typeDef.FullName); foreach (var prop in typeDef.Properties) { if (!prop.HasPublicGetter && !prop.HasPublicSetter) { continue; } var p = new MetadataProperty(prop.Name, types.GetValueOrDefault(prop.TypeFullName), currentType, false, prop.IsStatic, prop.HasPublicGetter, prop.HasPublicSetter); type.Properties.Add(p); } foreach (var eventDef in typeDef.Events) { var e = new MetadataEvent(eventDef.Name, types.GetValueOrDefault(eventDef.TypeFullName), types.GetValueOrDefault(typeDef.FullName), false); type.Events.Add(e); } //check for attached properties only on top level if (level == 0) { foreach (var methodDef in typeDef.Methods) { if (methodDef.Name.StartsWith("Set", StringComparison.OrdinalIgnoreCase) && methodDef.IsStatic && methodDef.IsPublic && methodDef.Parameters.Count == 2) { var name = methodDef.Name.Substring(3); type.Properties.Add(new MetadataProperty(name, types.GetValueOrDefault(methodDef.Parameters[1].TypeFullName), types.GetValueOrDefault(typeDef.FullName), true, false, true, true)); } } foreach (var fieldDef in typeDef.Fields) { if (fieldDef.IsStatic && fieldDef.IsPublic) { if ((fieldDef.IsRoutedEvent || fieldDef.Name.EndsWith("Event", StringComparison.OrdinalIgnoreCase))) { var name = fieldDef.Name; if (fieldDef.Name.EndsWith("Event", StringComparison.OrdinalIgnoreCase)) { name = name.Substring(0, name.Length - "Event".Length); } type.Events.Add(new MetadataEvent(name, types.GetValueOrDefault(fieldDef.ReturnTypeFullName), types.GetValueOrDefault(typeDef.FullName), true)); } else if (type.IsStatic) { type.Properties.Add(new MetadataProperty(fieldDef.Name, null, type, false, true, true, false)); } } } } if (typeDef.FullName == "Avalonia.AvaloniaObject") { type.IsAvaloniaObjectType = true; } typeDef = typeDef.GetBaseType(); level++; } type.HasAttachedProperties = type.Properties.Any(p => p.IsAttached); type.HasAttachedEvents = type.Events.Any(e => e.IsAttached); type.HasStaticGetProperties = type.Properties.Any(p => p.IsStatic && p.HasGetter); type.HasSetProperties = type.Properties.Any(p => !p.IsStatic && p.HasSetter); if (ctors?.Any() == true) { bool supportType = ctors.Any(m => m.Parameters[0].TypeFullName == "System.Type"); bool supportObject = ctors.Any(m => m.Parameters[0].TypeFullName == "System.Object" || m.Parameters[0].TypeFullName == "System.String"); if (types.TryGetValue(ctors.First().Parameters[0].TypeFullName, out MetadataType parType) && parType.HasHintValues) { type.SupportCtorArgument = MetadataTypeCtorArgument.HintValues; type.HasHintValues = true; type.HintValues = parType.HintValues; } else if (supportType && supportObject) { type.SupportCtorArgument = MetadataTypeCtorArgument.TypeAndObject; } else if (supportType) { type.SupportCtorArgument = MetadataTypeCtorArgument.Type; } else if (supportObject) { type.SupportCtorArgument = MetadataTypeCtorArgument.Object; } } } PostProcessTypes(types, metadata, resourceUrls, avaresValues); return(metadata); }
public static Metadata ConvertMetadata(IMetadataReaderSession provider) { var types = new Dictionary <string, MetadataType>(); var typeDefs = new Dictionary <MetadataType, ITypeInformation>(); var metadata = new Metadata(); types.Add(typeof(bool).FullName, new MetadataType() { Name = typeof(bool).FullName, IsEnum = true, EnumValues = new[] { "True", "False" } }); foreach (var asm in provider.Assemblies) { var aliases = new Dictionary <string, string>(); foreach ( var attr in asm.CustomAttributes.Where(a => a.TypeFullName == "Avalonia.Metadata.XmlnsDefinitionAttribute")) { aliases[attr.ConstructorArguments[1].Value.ToString()] = attr.ConstructorArguments[0].Value.ToString(); } foreach (var type in asm.Types.Where(x => !x.IsInterface && x.IsPublic)) { var mt = types[type.FullName] = ConvertTypeInfomation(type); typeDefs[mt] = type; metadata.AddType("clr-namespace:" + type.Namespace + ";assembly=" + asm.Name, mt); string alias = null; if (aliases.TryGetValue(type.Namespace, out alias)) { metadata.AddType(alias, mt); } } } foreach (var type in types.Values) { ITypeInformation typeDef; typeDefs.TryGetValue(type, out typeDef); while (typeDef != null) { foreach (var prop in typeDef.Properties) { if (prop.IsStatic || !prop.HasPublicSetter) { continue; } var p = new MetadataProperty { Name = prop.Name }; p.Type = types.GetValueOrDefault(prop.TypeFullName); type.Properties.Add(p); } foreach (var methodDef in typeDef.Methods) { if (methodDef.Name.StartsWith("Set") && methodDef.IsStatic && methodDef.IsPublic && methodDef.Parameters.Count == 2) { type.Properties.Add(new MetadataProperty() { Name = methodDef.Name.Substring(3), IsAttached = true, Type = types.GetValueOrDefault(methodDef.Parameters[1].TypeFullName) }); } } typeDef = typeDef.GetBaseType(); } type.HasAttachedProperties = type.Properties.Any(p => p.IsAttached); } return(metadata); }