搜索继承类
有这样一个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) 编辑 收藏 举报