Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Measuring relational inheritance distance between types

Does anyone know how I could (or if there is an existing algorithm) measure the relational distance between two .NET types?

By this I mean the number of 'steps' in the hierarchical tree that is required to get from object A to object B.

For example, if object A is a Button, and object B is a LinkButton, there would be 2 steps, Button -> WebControl -> LinkButton. Would I need to create my own static inheritance tree and use a path finding algorithm, or is there a way I can dynamically look at the inheritance structure of .NET to calculate the distance between two objects?

like image 587
Scotty Avatar asked Nov 23 '25 04:11

Scotty


1 Answers

Non-generic way (also you don't have to specify parent/child explicitly):

private static int CalulateDistanceOneWay(Type firstType, Type secondType)
{
  var chain = new List<Type>();
  while (firstType != typeof(object))
  {
    chain.Add(firstType);
    firstType = firstType.BaseType;
  }

  return chain.IndexOf(secondType);
}

// returns -1 for invalid input, distance between types otherwise
public static int CalculateDistance(Type firstType, Type secondType)
{
  int result = CalulateDistanceOneWay(firstType, secondType);
  if (result >= 0)
  {
    return result;
  }

  return CalulateDistanceOneWay(secondType, firstType);
}

EDIT: update to calculate cousins:

public class DistanceResult
{
  public Type SharedAncestor { get; private set; }
  public int FirstTypeDistance { get; private set; }
  public int SecondTypeDistance { get; private set; }

  public DistanceResult(Type sharedAncestor, int firstTypeDistance, int secondTypeDistance)
  {
    SharedAncestor = sharedAncestor;
    FirstTypeDistance = firstTypeDistance;
    SecondTypeDistance = secondTypeDistance;
  }
}

static DistanceResult CalculateDistance(Type firstType, Type secondType)
{
  var firstChain = new List<Type>();
  while (firstType != typeof(object))
  {
    firstChain.Add(firstType);
    firstType = firstType.BaseType;
  }
  firstChain.Add(typeof(object));

  var secondChain = new List<Type>();
  while(secondType != typeof(object))
  {
    secondChain.Add(secondType);
    secondType = secondType.BaseType;
  }
  secondChain.Add(typeof(object));

  for(var i = 0; i < secondChain.Count; i++)
  {
    var type = secondChain[i];
    int index = firstChain.IndexOf(type);
    if (index >= 0)
    {
      return new DistanceResult(firstChain[index], index, i);
    }
  }

  return null;
}
like image 83
Ondrej Svejdar Avatar answered Nov 24 '25 17:11

Ondrej Svejdar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!