예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }