Kevin Shan

搜索继承类

有这样一个Control,它需要获得所有BaseType的继承类。由于BaseType的继承类可能存在于当前程序集或者被当前工程引用的其他程序集,所以需要动态搜索可能存在的所有继承类。

为完成该功能,我写了下面两个方法,记录下来,为以后使用。

1,这个方法使用了DesignTime下的ITypeDiscoveryService,可以在DesignTime下使用。不过VS2008以下的ITypeDiscoveryService实现逻辑有Bug,不会搜索baseType所在的程序集,所有需要先搜索baseType所在的程序集。

        ///<summary>

        ///   Discovers available derived types that derived from baseType at design time.

        ///</summary>

        ///<param name="host">

        ///   The <see cref="IDesignerHost"/>.

        ///</param>

        ///<param name="baseType">

        ///   The base type to match.

        ///</param>

        ///<param name="excludeGlobalTypes">

        ///   Indicates whether types from all referenced assemblies should be checked.

        ///</param>

        ///<returns>

        ///   A collection of types that derived from baseType.

        ///</returns>

        public static Type[] GetDerivedTypes(IDesignerHost host, Type baseType, bool excludeGlobalTypes)

        {

            if (host == null)

            {

                throw new ArgumentNullException("host");

            }

            if (baseType == null)

            {

                throw new ArgumentNullException("baseType");

            }

            List<Type> derivedTypes = new List<Type>();

            //

            // Find derived types from base type's assembly.

            //

            if (!excludeGlobalTypes || !baseType.Assembly.GlobalAssemblyCache)

            {

                Type[] baseTypes = baseType.Assembly.GetTypes();

                foreach (Type type in baseTypes)

                {

                    if ((type.IsPublic || type.IsNestedPublic) && baseType.IsAssignableFrom(type))

                    {

                        derivedTypes.Add(type);

                    }

                }

            }

            //

            // Find derived types by ITypeDiscoveryService.

            //

            ITypeDiscoveryService service = host.GetService(typeof(ITypeDiscoveryService)) as ITypeDiscoveryService;

            if (service != null)

            {

                ICollection discoveryTypes = service.GetTypes(baseType, excludeGlobalTypes);

                foreach (Type type in discoveryTypes)

                {

                    if (!derivedTypes.Contains(type))

                    {

                        derivedTypes.Add(type);

                    }

                }

            }

            return derivedTypes.ToArray();

        }

补充:如果是搜索IComponent,还可以在DesignTime下使用IComponentDiscoveryService来完成。

2,这个方法会搜索当前Domain中所有程序集,注意,继承类所在的程序集会引用baseType所在的程序集,利用这一点可以做一定程度的性能优化。

        ///<summary>

        ///   Discovers available derived types that derived from baseType from current domain.

        ///</summary>

        ///<param name="baseType">

        ///   The base type to match.

        ///</param>

        ///<param name="excludeGlobalTypes">

        ///   Indicates whether types from all referenced assemblies should be checked.

        ///</param>

        ///<returns>

        ///   A collection of types that derived from baseType.

        ///</returns>

        public static Type[] GetDerivedTypes(Type baseType, bool excludeGlobalTypes)

        {

            if (baseType == null)

            {

                throw new ArgumentNullException("baseType");

            }

            List<Type> derivedTypes = new List<Type>();

            AssemblyName baseAssemblyName = baseType.Assembly.GetName();

            //

            // Find derived types from CurrentDomain.

            //

            Assembly[] assemblys = AppDomain.CurrentDomain.GetAssemblies();

            foreach (Assembly assembly in assemblys)

            {

                // Important, It can improve performance.

                bool needSearch = false;

                if (!excludeGlobalTypes || !assembly.GlobalAssemblyCache)

                {

                    if (string.Equals(assembly.FullName, baseAssemblyName.FullName, StringComparison.OrdinalIgnoreCase))

                    {

                        needSearch = true;

                    }

                    else

                    {

                        AssemblyName[] referencedAssemblies = assembly.GetReferencedAssemblies();

                        foreach (AssemblyName assemblyName in referencedAssemblies)

                        {

                            if (string.Equals(assemblyName.FullName, baseAssemblyName.FullName, StringComparison.OrdinalIgnoreCase))

                            {

                                needSearch = true;

                                break;

                            }

                        }

                    }

                }

                if (needSearch)

                {

                    Type[] types = assembly.GetTypes();

                    foreach (Type type in types)

                    {

                        if ((type.IsPublic || type.IsNestedPublic) && baseType.IsAssignableFrom(type) && !derivedTypes.Contains(type))

                        {

                            derivedTypes.Add(type);

                        }

                    }

                }

            }

            return derivedTypes.ToArray();

        }

posted on 2008-05-14 14:06  Kevin Shan  阅读(596)  评论(1编辑  收藏  举报