void LoadCommandContainer(TypeDescriptor containerType, AssemblyDescriber describer)
        {
            if (containerType.IsAbstract || !containerType.HasPublicParameterlessConstructor)
            {
                return;
            }

            var methods = describer.GetPublicMethods(containerType);

            var cmdMethods = (from method in methods
                              let commandAttr = method.APIAttributes.OfType <CommandAttribute>().FirstOrDefault()
                                                where commandAttr != null
                                                select new { method, commandAttr }).ToArray();

            if (cmdMethods.Length == 0)
            {
                return;
            }

            var dupeCommandNames =
                from i in cmdMethods
                group i by i.commandAttr.Name
                into g
                where g.Count() > 1
                select g;

            if (dupeCommandNames.Any())
            {
                throw new LoaderItemInitException(string.Format("Duplicate command names in container {0}", containerType));
            }

            var container    = CreateLoaderInstance <CommandContainer>(containerType);
            var commandInfos = new List <LoaderCommand>();

            foreach (var method in cmdMethods)
            {
                try
                {
                    var reflectedCmd = new ReflectedCommand(container, method.method, method.commandAttr);
                    var lcInfo       = new LoaderCommand(this, reflectedCmd);
                    reflectedCmd.LoaderCommand = lcInfo;
                    commandInfos.Add(lcInfo);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Could not initialize command {0} in container {1}: {2}", method.method.Name, containerType, ex.Message);
                }
            }

            var lccInfo = new LoaderCommandContainer(this, container, containerType);

            ExtensionStore.InitCommandContainer(lccInfo, commandInfos);
            container.Initialize(Hooks);
            AddItems(commandInfos);
            AddItem(lccInfo);
        }
        void LoadFacetFactory(TypeDescriptor factoryType, AssemblyDescriber describer)
        {
            if (factoryType.IsAbstract || !factoryType.HasPublicParameterlessConstructor)
            {
                return;
            }

            var attr = describer.GetClassAttributes(factoryType).OfType <FacetFactoryAttribute>().FirstOrDefault();

            var factory = CreateLoaderInstance <IFacetFactory>(factoryType);
            var info    = new LoaderFacetFactory(this, factory, factoryType, attr);

            ExtensionStore.InitFacetFactory(info);
            factory.Initialize(Hooks);
            AddItem(info);
        }
        void LoadFacetType(TypeDescriptor type, AssemblyDescriber describer)
        {
            if (!type.IsInterface && !type.IsAbstract)
            {
                if (!type.GetImplementedTypes(true).Any(x => x.IsInterface && x.Implements(typeof(IFacet))))
                {
                    throw new LoaderItemInitException("None of the interfaces implemented by facet class implements IFacet");
                }
            }

            LoaderAmbientFacet ambientInfo = null;

            if (!type.IsInterface)
            {
                var ambientAttr = describer.GetClassAttributes(type).OfType <AmbientFacetAttribute>().FirstOrDefault();

                if (ambientAttr != null)
                {
                    if (!type.HasPublicParameterlessConstructor || type.IsAbstract)
                    {
                        throw new LoaderItemInitException("No public parameterless constructor for ambient facet type");
                    }

                    var facet = CreateLoaderInstance <IFacet>(type);
                    facet.Initialize(Hooks);
                    ambientInfo = new LoaderAmbientFacet(this, ambientAttr.Token, facet,
                                                         new FacetMoniker(ambientAttr.Token, type, facet.DisplayName));
                }
            }

            var info = new LoaderFacetType(this, type);

            ExtensionStore.InitFacetType(info);
            AddItem(info);

            if (ambientInfo != null)
            {
                AddItem(ambientInfo);
            }
        }
        void Initialize(AssemblyDescriber describer, TypeDescriptor[] types)
        {
            ExtensionStore.InitExtension(this);

            foreach (var type in types
                     .OrderBy(x => x.IsInterface ? 0 : 1)
                     .ThenBy(x => x.Implements(typeof(IFacet)) ? 0 : 1))
            {
                try
                {
                    if (type.Implements(typeof(IFacet)))
                    {
                        LoadFacetType(type, describer);
                    }
                    else if (type.Implements(typeof(IFacetFactory)))
                    {
                        LoadFacetFactory(type, describer);
                    }
                    else if (type.Implements(typeof(CommandContainer)))
                    {
                        LoadCommandContainer(type, describer);
                    }
                    else if (type.Implements(typeof(IConfigurator)))
                    {
                        if (!type.IsAbstract && type.HasPublicParameterlessConstructor)
                        {
                            AddItem(new LoaderConfiguratorType(this, type));
                        }
                    }
                }
                catch (LoaderItemInitException e)
                {
                    Debug.WriteLine("Could not load type {0}: {1}", type.FullName, e.Message);
                }
            }
        }