在扩展方法中,如何基于实现类创建对象。所以在下面的代码中我想添加一个“AddRelationship”扩展方法,但是我不确定在扩展方法中我如何创建一个Relationship对象?即不想将扩展方法与这种特定的关系实现联系起来
public static class TopologyExtns
{
public static void AddNode<T>(this ITopology<T> topIf, INode<T> node)
{
topIf.Nodes.Add(node.Key, node);
}
public static INode<T> FindNode<T>(this ITopology<T> topIf, T searchKey)
{
return topIf.Nodes[searchKey];
}
public static bool AddRelationship<T>(this ITopology<T> topIf, INode<T> parentNode, INode<T> childNode)
{
var rel = new RelationshipImp(); // ** How do I create an object from teh implementation
// Add nodes to Relationship
// Add relationships to Nodes
}
}
public interface ITopology<T>
{
//List<INode> Nodes { get; set; }
Dictionary<T, INode<T> > Nodes { get; set; }
}
public interface INode<T>
{
// Properties
List<IRelationship<T>> Relationships { get; set; }
T Key { get; }
}
public interface IRelationship<T>
{
// Parameters
INode<T> Parent { get; set; }
INode<T> Child { get; set; }
}
namespace TopologyLibrary_Client
{
class RelationshipsImp : IRelationship<string>
{
public INode<string> Parent { get; set; }
public INode<string> Child { get; set; }
}
}
public class TopologyImp<T> : ITopology<T>
{
public Dictionary<T, INode<T>> Nodes { get; set; }
public TopologyImp()
{
Nodes = new Dictionary<T, INode<T>>();
}
}
感谢
答案 0 :(得分:2)
您可以添加一个额外的类型参数来表示关系实现类,指定它必须是IRelationship
的约束并且具有无参数构造函数:
public static bool AddRelationship<T,R>(this ITopology<T> topIf, INode<T> parentNode, INode<T> childNode)
where R : IRelationship, new() {
var rel = new R();
// ...
}
然后你应该像这样调用它来指定IRelationship具体类型('R'类型参数):
topology.AddRelationship<string, RelationshipImp>(parentNode, childNode);
编辑:替代方法,没有扩展方法:您定义(并稍后实例化)RelationshipFactory类:
class RelationshipFactory<R>
where R : IRelationship, new(){
// no longer an extension method:
public static bool AddRelationship<T>(ITopology<T> topIf, INode<T> parentNode, INode<T> childNode) {
var rel = new R();
// ...
}
}
答案 1 :(得分:1)
一种方法是将责任推送到ITopology<T>
或INode<T>
类,方法是修改其接口以支持IRelationship<T>
工厂方法,例如ITopology<T>
可以修改为:
public interface ITopology<T>
{
IRleationship<T> CreateRelationship(INode<T> parent, INode<T> child);
Dictionary<T, INode<T> > Nodes { get; set; }
}
然后AddRelationship<T>
看起来像:
public static bool AddRelationship<T>(this ITopology<T> topIf, INode<T> parentNode, INode<T> childNode)
{
var relationship = topIf->CreateRelationship(parentNode, childNode);
// ...
}
由于您正在使用扩展方法,因此可能无法或不希望修改接口,但这是一个选项。
答案 2 :(得分:1)
解决有关您的设计的另一个(可能的)问题。当您只需将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);
}
}
无需扩展方法或中间IRelationship类。这一切都取决于修改接口的能力,并且INode只能有一个父接口。
编辑(根据OP的评论):
考虑到您在使扩展方法的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"));