Пример #1
0
        private async Task InitRouteTable()
        {
            var apps = AdditionalAssemblies == null ? new[] { Assembly.GetEntryAssembly() } : new[] { Assembly.GetEntryAssembly() }.Concat(AdditionalAssemblies).Where(a => a != null);
            var componentTypes = apps.SelectMany(a => a !.ExportedTypes.Where(t => typeof(IComponent).IsAssignableFrom(t)));

            foreach (var componentType in componentTypes)
            {
                var routeAttributes = componentType.GetCustomAttributes <RouteAttribute>(false);
                foreach (var template in routeAttributes.Select(t => t.Template))
                {
                    RouteTable.TryAdd(template.Trim('/'), componentType);
                }
            }
            Navigator.LocationChanged += Navigator_LocationChanged;

            await InvokeAsync(() => AddTabByUrl(Navigator.ToBaseRelativePath(Navigator.Uri)));
        }
        /// <summary>
        /// Compose an object: all properties of the object decorated with an
        /// Import or ImportMany attribute, will be instantiated accordingly.
        /// Alternatively, if a Type if provided, it will be scanned for public
        /// static properties marked for import.
        /// </summary>
        /// <param name="root">The object to compose, or a type if composing must be done for static properties of a class</param>
        public static void Compose(object root)
        {
            if (root == null)
            {
                return;
            }

            PropertyInfo[] infos;
            object         obj;

            if (root is Type rootType)
            {
                obj   = null;
                infos = rootType.GetProperties(
                    BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
            }
            else
            {
                obj   = root;
                infos = root.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            }

            foreach (var prop in infos)
            {
                var browsable = prop.GetCustomAttribute <BrowsableAttribute>();
                if (browsable != null && !browsable.Browsable)
                {
                    continue;
                }

                var attribs = prop.GetCustomAttributes().ToArray();
                if (attribs.Length == 0 && !prop.PropertyType.IsValueType && prop.PropertyType != typeof(string))
                {
                    // Recursive composition is only allowed for generic types for now
                    if (prop.PropertyType.IsGenericType)
                    {
                        Compose(prop.GetValue(root));
                    }
                }

                foreach (var attrib in attribs)
                {
                    ExportedType[] exportedTypes;
                    switch (attrib)
                    {
                    case ImportAttribute ia:
                        exportedTypes = ExportedTypes.Where(x => x.ExposedType == prop.PropertyType).ToArray();
                        if (exportedTypes.Length == 0)
                        {
                            throw new Exception($"No exported type matched imported type {prop.PropertyType.FullName}");
                        }
                        if (exportedTypes.Length > 1)
                        {
                            throw new AmbiguousMatchException($"More than one exported types match imported type {prop.PropertyType.FullName}");
                        }
                        object instance;
                        switch (exportedTypes[0].Many)
                        {
                        case true:
                            instance = CreateAndCompose(exportedTypes[0].ActualType);
                            break;

                        default:
                            instance = GetSingleton(exportedTypes[0].ActualType);
                            break;
                        }
                        prop.SetValue(obj, instance);
                        break;

                    case ImportManyAttribute ima:
                        if (!prop.PropertyType.IsGenericType)
                        {
                            throw new Exception("ImportMany can only be applied on generic types");
                        }

                        exportedTypes = ExportedTypes.Where(x => x.ExposedType == ima.ImportedType).ToArray();
                        var constructedListType = typeof(List <>).MakeGenericType(ima.ImportedType);
                        var instanceList        = (IList)Activator.CreateInstance(constructedListType);
                        foreach (var t in exportedTypes)
                        {
                            var listItem = instance = CreateAndCompose(t.ActualType);
                            instanceList.Add(listItem);
                        }

                        try
                        {
                            prop.SetValue(obj, instanceList);
                        }
                        catch (ArgumentException)
                        {
                            throw new Exception("No setter found for property " + prop.Name + ", or wrong type");
                        }
                        break;
                    }
                }
            }
        }