如何找到两个类型之间常见的一种类型最适合? [英] How to find the best fit of common type between two types?
问题描述
Here're使用两个扩展方法
公共静态类型FindInterfaceWith(这种类型的1型,2型型){
//返回最适合普通实现的接口
}
公共静态类型FindBaseClassWith(这种类型的1型,2型型){
//返回最衍生公共基类的
}
-
FindInterfaceWith
收益空
,如果他们没有共同实现的接口。
-
FindBaseClassWith
收益System.Object的
,如果他们没有更衍生物共同的基类。 -
FindBaseClassWith
收益空
如果参数之一是一个接口。 - 这两个他们返回
空
如果任何参数是空
。
和方法的签名在最后的解决办法是这样的:
公共静态类型FindEqualTypeWith(这种类型的1型,2型型){
//应该是什么吗?
}
反思和LINQ被限制使用,除非有没有其他方法
有没有好的方法可以找到常见的一种类型 1型
之间的最佳匹配 2型
?
还是有更好的东西来实现这一目标?
更新#1
< 据@Akim的答案,我终于张贴在Q&放大器解决方案; A形式
更新#0:
这是我个人的理解,因为在 应用于实现多个接口的能力的一类,在 FindInterfaceWith
可能需要了 FindBaseClassWith
内部调用;否则型的最佳选择将是不可判定的。
如果这一假设是正确的,那么 FindInterfaceWith
变得冗余的方法;因为之间的唯一区别的 FindInterfaceWith
和 FindEqualTypeWith
是:
的 FindInterfaceWith
收益空
如果有类的最佳选择;而 FindEqualTypeWith
直接返回准确的类。的
否则,他们都返回接口的最佳选择。
这是有关说法最初的假设是不合理的。也就是说, FindInterfaceWith
无法执行,如果 FindEqualTypeWith
未的。这将推断,任何当前现有的实现 FindInterfaceWith
的,包括我的。
下面是我实现的:
FindEqualTypeWith
, FindBaseClassWith
和 FindInterfaceWith
实施
//提供公共基类或实现的接口
公共静态类型FindEqualTypeWith(这种类型typeLeft,键入typeRight)
{
如果( typeLeft == NULL || typeRight == NULL)返回NULL;
VAR commonBaseClass = typeLeft.FindBaseClassWith(typeRight)? typeof运算(对象);
返回commonBaseClass.Equals(typeof运算(对象))
? typeLeft.FindInterfaceWith(typeRight)
:commonBaseClass;
}
//寻找共同的基类(或具体或抽象)
公共静态类型FindBaseClassWith(这种类型typeLeft,键入typeRight)
{
如果(typeLeft == NULL || typeRight == NULL)返回NULL;
返回typeLeft
.GetClassHierarchy()
.Intersect(typeRight.GetClassHierarchy())
.FirstOrDefault(类型=>!type.IsInterface);
}
//寻找共同实现的接口
//有可能为一个类实现多个接口,
//在这种情况下返回第一个基于通用接口
公共静态类型FindInterfaceWith(这种类型typeLeft,键入typeRight)
{
如果(typeLeft == NULL || typeRight == NULL)返回NULL;
返回typeLeft
.GetInterfaceHierarchy()
.Intersect(typeRight.GetInterfaceHierarchy())
.FirstOrDefault();
}
//遍历接口hierarhy
公共静态的IEnumerable<类型> GetInterfaceHierarchy(这种类型)
{
如果(type.IsInterface)返回新的[] {}型.AsEnumerable();
返回类型
.GetInterfaces()
.OrderByDescending(电流=> current.GetInterfaces()计数()。)
.AsEnumerable();
}
//阶级hierarhy
公共静态的IEnumerable< interate;类型> GetClassHierarchy(这种类型)
{
如果(类型== NULL)产量突破;
型typeInHierarchy =类型;
做
{
收益率的回报typeInHierarchy;
typeInHierarchy = typeInHierarchy.BaseType;
}
,而(typeInHierarchy = NULL&放大器;!&安培;!typeInHierarchy.IsInterface);
}
关于备注 FindInterfaceWith
实施
这是实现任何接口或者的IEnumerable
或的IEnumerable< T>
将别人,有什么我认为不正确
<的H3>开放式问题
FindInterfaceWith
的 C#的允许多个接口在一个类中实现,在这种情况下,接口第一个将被 FindInterfaceWith
,,因为没有办法怎么知道哪个接口 IA
或 IB
表现一般最好在下面的示例
的接口和类层次结构
公共接口IBase的{}
公共接口ISomething {}
公共接口IDerivied:IBase的{}
公共接口IDeriviedRight:IDerivied {}
公共接口IDeriviedLeft:IDerivied,IDisposable的{}
公共类AnotherDisposable:IDisposable接口{
公共无效的Dispose(){
}
}
公共类DeriviedLeft:IDeriviedLeft {
公共无效的Dispose(){
}
}
公共类SubDeriviedLeft:DeriviedLeft {}
公共类SecondSubDeriviedLeft:DeriviedLeft {}
公共类ThirdSubDeriviedLeft:DeriviedLeft,ISomething {}
公共类另一个{}
公共类DeriviedRight:IDeriviedRight {}
测试用例
和使用 NUnit的
断言组测试用例:
FindBaseClassWith
断言例如
// FindBaseClassWith返回null如果参数中的一个是一个接口。
// FindBaseClassWith返回null如果任何参数为空。
Assert.That(typeof运算(DeriviedLeft).FindBaseClassWith(typeof运算(DeriviedLeft)),Is.EqualTo(typeof运算(DeriviedLeft)));
FindInterfaceWith
断言例如
// FindInterfaceWith如果他们没有共同实现的接口返回null。
// FindBaseClassWith返回null如果任何参数为空。
Assert.That(typeof运算(DeriviedLeft).FindInterfaceWith(typeof运算(DeriviedLeft)),Is.EqualTo(typeof运算(IDeriviedLeft)));
FindEqualTypeWith
断言例如
Assert.That(typeof运算(DeriviedLeft).FindEqualTypeWith(typeof运算(DeriviedLeft)),Is.SameAs(typeof运算(DeriviedLeft)));
作者在代码审查
的在 codereview.stackexchange.com
PS :
全源可用[的这里]
Here're two extension methods for use
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
}
FindInterfaceWith
returnsnull
if they don't have common implemented interface.FindBaseClassWith
returnsSystem.Object
if they have no more derivative common base class.FindBaseClassWith
returnsnull
if one of parameters was an interface.- Both they return
null
if any of parameter wasnull
.
And the signature of method in finally solution would be like:
public static Type FindEqualTypeWith(this Type type1, Type type2) {
// what should be here?
}
Reflection and Linq are restricted to use, except there are no other ways.
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 #1:
According to the answer of @Akim, I finally posted a solution in a Q&A form
update #0:
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 FindEqualTypeWith
is:
FindInterfaceWith
returns null
if there was a best choice of class; while FindEqualTypeWith
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 FindEqualTypeWith
is not. This would infer that any of current existing implementation of FindInterfaceWith
including mine.
Here is my implementation:
FindEqualTypeWith
, FindBaseClassWith
and FindInterfaceWith
implementations
// provide common base class or implemented interface
public static Type FindEqualTypeWith(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);
}
Remark regarding FindInterfaceWith
implementation
Any interfaces that implements either IEnumerable
or IEnumerable<T>
will be selected before others, what I considered not to be correct
Open ended question of FindInterfaceWith
c# 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 sample
Interfaces 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 cases
And 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)));
FindEqualTypeWith
assertions example
Assert.That(typeof(DeriviedLeft).FindEqualTypeWith(typeof(DeriviedLeft)), Is.SameAs(typeof(DeriviedLeft)));
Discussion at CodeReview
Review of this answer at codereview.stackexchange.com
ps:
Full sources available [here]
这篇关于如何找到两个类型之间常见的一种类型最适合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!