Решение другой (возможной) проблемы с вашим дизайном. Почему вы используете методы расширения, когда вы можете просто поместить метод AddRelationship в реализацию вашей топологии? Есть ли особая необходимость использовать методы расширения в этом случае? Кроме того, будет ли когда-нибудь случай, когда один узел может иметь много родителей?
Я думаю, что-то вроде этого будет в порядке:
public interface INode<T>
{
// Properties
INode<T> Parent { get; }
IEnumerable<INode<T>> Children { get; }
String Key { get; }
void AddChild(INode<T> child);
}
public class Node<T> : INode<T>
{
public Node(String key) : this(key, null) {}
public Node(String key, INode<T> parent)
{
this.Parent = parent;
this.Children = new List<T>();
this.Key = key;
}
public virtual INode<T> Parent { get; protected set; }
public virtual String Key { get; protected set; }
public virtual List<T> Children { get; protected set; }
public void AddChild(INode<T> node)
{
this.Children.Add(node);
}
}
Нет необходимости в методах расширения или промежуточном классе IRelationhip. Все это зависит от возможности изменить интерфейс для одного, и что у INode может быть только один родительский элемент.
Редактировать (на основе комментария от ОП):
Учитывая, что вы специально сделали API для метода расширения более чистым, вы можете сделать это:
public static bool AddRelationship(this INode<T> node, IRelationship<T> relationship)
{
if (node.Relationships == null)
node.Relationships = new List<T>;
if (relationship == null) throw new ArgumentNullException("relationship");
node.Relationships.Add(relationship);
return true; // I'd make this method void
}
И тогда вызов этого будет:
INode node = new Node<String>("some key");
INode someParent = new Node<String>("some parent key");
INode someChild = new Node<String>("some child key");
node.AddRelationship(new RelationshipImp(someParent, someChild));
Я не проверял это, так что я могу быть не в курсе, где указаны дженерики. Я не знаю, может ли механизм вывода вывести то, что ему нужно здесь.
Что интересно, почему вы решили использовать «узел имеет много родителей и много детей» вместо «узел имеет соседей»? Недавно я построил структуру графа и нашел словарь или список узлов более чем подходящим для моделирования направлений. Просто снова перечитываю исходный вопрос - должны ли отношения храниться в топологии? В этом было бы гораздо больше смысла, и это то, что вы пытаетесь сделать с помощью своего оригинального метода расширения.
В случае, когда отношения находятся в Топологии, я бы пошел с другим опубликованным ответом:
public static bool AddRelationship<T,R>(this ITopology<T> top, INode<T> parent, INode<T> child ) where R : IRelationship, new
{
IRelationship<T> rel = new R();
rel.Parent = parent;
rel.Child = child;
top.Relationships.Add(rel);
}
И называя это:
ITopology<String> top = new TopologyImp<String>;
top.AddRelationship<RelationshipImp>(new NodeImp("parent"), new NodeImp("Child"));