FindInterfaceWith 的开放式问题 上查看此答案 ps :可用的完整资源为[此处] Here're two extension methods for usepublic static Type FindInterfaceWith(this Type type1, Type type2) { // returns most suitable common implemented interface}public static Type FindBaseClassWith(this Type type1, Type type2) { // returns most derivative of common base class}FindInterfaceWith returns null if they don't have common implemented interface.FindBaseClassWith returns System.Object if they have no more derivative common base class.FindBaseClassWith returns null if one of parameters was an interface.Both they return null if any of parameter was null.And the signature of method in finally solution would be like:public static Type FindAssignableWith(this Type type1, Type type2) { // what should be here?}Reflection and Linq are restricted to use, except there are no other way.Are there good ways to find the best fit of common type between type1 and type2?Or are there something better to achieve this?update:By my personal understanding, because of the ability to implement multiple interfaces with a class, the FindInterfaceWith could possibly need to call FindBaseClassWith internally; otherwise the best choice of type would be undecidable.If this supposition was correct, then the FindInterfaceWith becomes a redundant method; because of the only difference between FindInterfaceWith and FindAssignableWith is:FindInterfaceWith returns null if there was a best choice of class; while FindAssignableWith returns the exact class directly.Otherwise, they both return a best choice of interface.This is about saying the original assumption was irrational. That is, FindInterfaceWith cannot be implemented if FindAssignableWith is not. 解决方案 Here is my implementation:FindAssignableWith, FindBaseClassWith and FindInterfaceWith implementations// provide common base class or implemented interfacepublic static Type FindAssignableWith(this Type typeLeft, Type typeRight){ if(typeLeft == null || typeRight == null) return null; var commonBaseClass = typeLeft.FindBaseClassWith(typeRight) ?? typeof(object); return commonBaseClass.Equals(typeof(object)) ? typeLeft.FindInterfaceWith(typeRight) : commonBaseClass;}// searching for common base class (either concrete or abstract)public static Type FindBaseClassWith(this Type typeLeft, Type typeRight){ if(typeLeft == null || typeRight == null) return null; return typeLeft .GetClassHierarchy() .Intersect(typeRight.GetClassHierarchy()) .FirstOrDefault(type => !type.IsInterface);}// searching for common implemented interface// it's possible for one class to implement multiple interfaces,// in this case return first common based interfacepublic static Type FindInterfaceWith(this Type typeLeft, Type typeRight){ if(typeLeft == null || typeRight == null) return null; return typeLeft .GetInterfaceHierarchy() .Intersect(typeRight.GetInterfaceHierarchy()) .FirstOrDefault();}// iterate on interface hierarhypublic static IEnumerable<Type> GetInterfaceHierarchy(this Type type){ if(type.IsInterface) return new [] { type }.AsEnumerable(); return type .GetInterfaces() .OrderByDescending(current => current.GetInterfaces().Count()) .AsEnumerable();}// interate on class hierarhypublic static IEnumerable<Type> GetClassHierarchy(this Type type){ if(type == null) yield break; Type typeInHierarchy = type; do { yield return typeInHierarchy; typeInHierarchy = typeInHierarchy.BaseType; } while(typeInHierarchy != null && !typeInHierarchy.IsInterface);}Remark regarding FindInterfaceWith implementationAny interfaces that implements either IEnumerable or IEnumerable<T> will be selected before others, what I considered not to be correctOpen ended question of FindInterfaceWithc# allow multiple interfaces to be implemented in one class, in this case first one of interfaces will be returned by FindInterfaceWith, because there is no way how to know which of interfaces IA or IB are preferable in general in following sampleInterfaces and classes hierarchy public interface IBase {} public interface ISomething {} public interface IDerivied: IBase {} public interface IDeriviedRight: IDerivied {} public interface IDeriviedLeft: IDerivied, IDisposable {} public class AnotherDisposable: IDisposable { public void Dispose() { } } public class DeriviedLeft: IDeriviedLeft { public void Dispose() { } } public class SubDeriviedLeft: DeriviedLeft {} public class SecondSubDeriviedLeft: DeriviedLeft {} public class ThirdSubDeriviedLeft: DeriviedLeft, ISomething {} public class Another {} public class DeriviedRight: IDeriviedRight {}Test casesAnd set of test cases using NUnit assertions:FindBaseClassWith assertions example// FindBaseClassWith returns null if one of parameters was an interface.// FindBaseClassWith return null if any of parameter was null.Assert.That(typeof(DeriviedLeft).FindBaseClassWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(DeriviedLeft)));FindInterfaceWith assertions example// FindInterfaceWith returns null if they don't have common implemented interface.// FindBaseClassWith return null if any of parameter was null.Assert.That(typeof(DeriviedLeft).FindInterfaceWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(IDeriviedLeft)));FinAssignableWith assertions exampleAssert.That(typeof(DeriviedLeft).FindAssignableWith(typeof(DeriviedLeft)), Is.SameAs(typeof(DeriviedLeft)));Discussion at CodeReviewReview of this answer at codereview.stackexchange.comps:Full sources available [here] 这篇关于如何找到两种类型(重复的)中最小的可分配类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-15 07:16