Skip to content

Instantly share code, notes, and snippets.

@akimboyko
Last active December 10, 2015 13:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akimboyko/4442677 to your computer and use it in GitHub Desktop.
Save akimboyko/4442677 to your computer and use it in GitHub Desktop.
void Main()
{
// FindBaseClassWith
Assert.That(typeof(DeriviedLeft).FindBaseClassWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(DeriviedLeft)));
Assert.That(typeof(DeriviedLeft).FindBaseClassWith(typeof(SubDeriviedLeft)), Is.EqualTo(typeof(DeriviedLeft)));
Assert.That(typeof(DeriviedLeft).FindBaseClassWith(typeof(DeriviedRight)), Is.EqualTo(typeof(object)));
Assert.That(typeof(DeriviedLeft).FindBaseClassWith(typeof(object)), Is.EqualTo(typeof(object)));
Assert.That(typeof(DeriviedLeft).FindBaseClassWith(typeof(Another)), Is.EqualTo(typeof(object)));
Assert.That(typeof(DeriviedRight).FindBaseClassWith(typeof(DeriviedRight)), Is.EqualTo(typeof(DeriviedRight)));
Assert.That(typeof(DeriviedRight).FindBaseClassWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(object)));
Assert.That(typeof(object).FindBaseClassWith(typeof(object)), Is.EqualTo(typeof(object)));
Assert.That(typeof(DeriviedLeft).FindBaseClassWith(typeof(IDerivied)), Is.Null);
Assert.That(typeof(IDerivied).FindBaseClassWith(typeof(IDerivied)), Is.Null);
Assert.That(typeof(IDerivied).FindBaseClassWith(null), Is.Null);
// FindInterfaceWith
Assert.That(typeof(DeriviedLeft).FindInterfaceWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(IDeriviedLeft)));
Assert.That(typeof(DeriviedLeft).FindInterfaceWith(typeof(SubDeriviedLeft)), Is.EqualTo(typeof(IDeriviedLeft)));
Assert.That(typeof(DeriviedLeft).FindInterfaceWith(typeof(DeriviedRight)), Is.EqualTo(typeof(IDerivied)));
Assert.That(typeof(DeriviedLeft).FindInterfaceWith(typeof(object)), Is.Null);
Assert.That(typeof(DeriviedLeft).FindInterfaceWith(typeof(Another)), Is.Null);
Assert.That(typeof(DeriviedLeft).FindInterfaceWith(typeof(AnotherDisposable)), Is.EqualTo(typeof(IDisposable)));
Assert.That(typeof(DeriviedRight).FindInterfaceWith(typeof(DeriviedRight)), Is.EqualTo(typeof(IDeriviedRight)));
Assert.That(typeof(DeriviedRight).FindInterfaceWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(IDerivied)));
Assert.That(typeof(object).FindInterfaceWith(typeof(object)), Is.Null);
Assert.That(typeof(object).FindInterfaceWith(null), Is.Null);
Assert.That(typeof(char[]).FindInterfaceWith(typeof(string)), Is.SameAs(typeof(IEnumerable<char>)));
Assert.That(typeof(string).FindInterfaceWith(typeof(char[])), Is.SameAs(typeof(IEnumerable<char>)));
// FindEqualTypeWith
Assert.That(typeof(DeriviedLeft).FindEqualTypeWith(typeof(DeriviedLeft)), Is.SameAs(typeof(DeriviedLeft)));
Assert.That(typeof(DeriviedLeft).FindEqualTypeWith(typeof(SubDeriviedLeft)), Is.EqualTo(typeof(DeriviedLeft)));
Assert.That(typeof(DeriviedLeft).FindEqualTypeWith(typeof(DeriviedRight)), Is.EqualTo(typeof(IDerivied)));
Assert.That(typeof(DeriviedLeft).FindEqualTypeWith(typeof(object)), Is.Null);
Assert.That(typeof(DeriviedLeft).FindEqualTypeWith(typeof(Another)), Is.Null);
Assert.That(typeof(DeriviedLeft).FindEqualTypeWith(typeof(AnotherDisposable)), Is.EqualTo(typeof(IDisposable)));
Assert.That(typeof(SubDeriviedLeft).FindEqualTypeWith(typeof(DeriviedRight)), Is.EqualTo(typeof(IDerivied)));
Assert.That(typeof(SubDeriviedLeft).FindEqualTypeWith(typeof(SecondSubDeriviedLeft)), Is.EqualTo(typeof(DeriviedLeft)));
Assert.That(typeof(SubDeriviedLeft).FindEqualTypeWith(typeof(ThirdSubDeriviedLeft)), Is.EqualTo(typeof(DeriviedLeft)));
Assert.That(typeof(DeriviedRight).FindEqualTypeWith(typeof(DeriviedRight)), Is.EqualTo(typeof(DeriviedRight)));
Assert.That(typeof(DeriviedRight).FindEqualTypeWith(typeof(DeriviedLeft)), Is.EqualTo(typeof(IDerivied)));
Assert.That(typeof(object).FindEqualTypeWith(typeof(object)), Is.Null);
Assert.That(typeof(object).FindEqualTypeWith(null), Is.Null);
Assert.That(typeof(List<string>).FindEqualTypeWith(typeof(HashSet<string>)), Is.SameAs(typeof(ICollection<string>)));
Assert.That(typeof(List<string>).FindEqualTypeWith(typeof(LinkedList<string>)), Is.SameAs(typeof(ICollection<string>)));
Assert.That(typeof(string[]).FindEqualTypeWith(typeof(LinkedList<string>)), Is.SameAs(typeof(ICollection<string>)));
Assert.That(typeof(string[]).FindEqualTypeWith(typeof(string)), Is.SameAs(typeof(ICloneable)));
Assert.That(typeof(int).FindEqualTypeWith(typeof(string)), Is.SameAs(typeof(IComparable)));
Assert.That(typeof(string).FindEqualTypeWith(typeof(IConvertible)), Is.SameAs(typeof(IConvertible)));
Assert.That(typeof(IConvertible).FindEqualTypeWith(typeof(string)), Is.SameAs(typeof(IConvertible)));
Assert.That(typeof(ICollection).FindEqualTypeWith(typeof(Array)), Is.SameAs(typeof(ICollection)));
Assert.That(typeof(Array).FindEqualTypeWith(typeof(ICollection)), Is.SameAs(typeof(ICollection)));
Assert.That(typeof(Array).FindEqualTypeWith(typeof(string)), Is.SameAs(typeof(ICloneable)));
Assert.That(typeof(string).FindEqualTypeWith(typeof(Array)), Is.SameAs(typeof(ICloneable)));
Assert.That(typeof(char[]).FindEqualTypeWith(typeof(string)), Is.SameAs(typeof(IEnumerable<char>)));
Assert.That(typeof(string).FindEqualTypeWith(typeof(char[])), Is.SameAs(typeof(IEnumerable<char>)));
}
public interface IBase { }
public interface IDerivied : IBase { }
public interface IDeriviedLeft : IDerivied, IDisposable { }
public interface IDeriviedRight : IDerivied { }
public interface ISomething { }
public class DeriviedLeft : IDeriviedLeft
{
public void Dispose() { }
}
public class SubDeriviedLeft : DeriviedLeft { }
public class SecondSubDeriviedLeft : DeriviedLeft { }
public class ThirdSubDeriviedLeft : DeriviedLeft, ISomething { }
public class DeriviedRight : IDeriviedRight { }
public class Another { }
public class AnotherDisposable : IDisposable
{
public void Dispose() { }
}
}
public static class TypeHelper
{
// 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);
}
@akimboyko
Copy link
Author

Fix for type1=typeof(String), type2=typeof(IConvertable) or type1=typeof(ICollection) and type2=typeof(Array).

@akimboyko
Copy link
Author

string vs. IConvertible → IConvertible
ICollection vs. Array → ICollection

@akimboyko
Copy link
Author

Refactoring

@akimboyko
Copy link
Author

Fix GetInterfaceHierarchy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment