Ken*_*Kin 13 c# reflection types
这是两种使用的扩展方法
public 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
}
Run Code Online (Sandbox Code Playgroud)
FindInterfaceWith返回null如果他们没有共同实现的接口.FindBaseClassWith返回System.Object,如果他们有没有更多的衍生物共同的基类.FindBaseClassWithnull如果其中一个参数是一个接口,则返回null如果有任何参数,它们都会返回null.最终解决方案中的方法签名如下:
public static Type FindAssignableWith(this Type type1, Type type2) {
// what should be here?
}
Run Code Online (Sandbox Code Playgroud)
反射和Linq仅限使用,除非没有其他方法.
有没有好的方法之间找到共同类型的最适合type1和type2?
或者有更好的事情来实现这一目标吗?
更新:
根据我个人的理解,由于能够使用类实现多个接口,FindInterfaceWith可能需要在FindBaseClassWith内部调用; 否则最好的选择类型将是不可判定的.
如果这个假设是正确的,那么FindInterfaceWith它就变成了一个冗余的方法; 因为之间的唯一区别的FindInterfaceWith和FindAssignableWith是:
FindInterfaceWithnull如果有最好的选择,则返回; while FindAssignableWith直接返回确切的类.
否则,它们都会返回最佳的界面选择.
这是关于说最初的假设是不合理的.也就是说,FindInterfaceWith如果FindAssignableWith不是,则无法实施.
Aki*_*kim 10
这是我的实现:
FindAssignableWith,FindBaseClassWith并FindInterfaceWith实现// provide common base class or implemented interface
public 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 interface
public 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 hierarhy
public 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 hierarhy
public 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);
}
Run Code Online (Sandbox Code Playgroud)
FindInterfaceWith实施的评论在其他人之前实现IEnumerable或IEnumerable<T>将被选择的任何接口,我认为不正确
FindInterfaceWithc#允许在一个类中实现多个接口,在这种情况下,第一个接口将被返回FindInterfaceWith,因为在以下示例中通常无法知道哪个接口IA或IB更优选

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 {}
Run Code Online (Sandbox Code Playgroud)
使用NUnit断言的一组测试用例:
FindBaseClassWith 断言的例子
// 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)));
Run Code Online (Sandbox Code Playgroud)
FindInterfaceWith 断言的例子
// 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)));
Run Code Online (Sandbox Code Playgroud)
FinAssignableWith 断言的例子
Assert.That(typeof(DeriviedLeft).FindAssignableWith(typeof(DeriviedLeft)), Is.SameAs(typeof(DeriviedLeft)));
Run Code Online (Sandbox Code Playgroud)
回顾这个答案 codereview.stackexchange.com
ps:
完整资源[ 这里 ]
| 归档时间: |
|
| 查看次数: |
2097 次 |
| 最近记录: |