【发布时间】:2019-06-15 13:31:31
【问题描述】:
我正在尝试为方法链接构建一个流畅的 API。这些是方法
public interface IBaseRelationships
{
IEnumerable<Person> Parents(IEnumerable<Person> people);
IEnumerable<Person> Children(IEnumerable<Person> people);
IEnumerable<Person> Siblings(IEnumerable<Person> people);
}
以及实现
public class BaseRelationships : IBaseRelationships
{
public BaseRelationships(IFamilyGraph familyGraph)
{
FamilyGraph = familyGraph;
}
public IFamilyGraph FamilyGraph { get; }
public IEnumerable<Person> Parents(IEnumerable<Person> people)
{
List<Person> result = new List<Person>();
foreach (var person in people)
{
IPersonRelationships personRelationships = FamilyGraph.Get(person);
result.AddRange(personRelationships.Parents);
}
return result;
}
public IEnumerable<Person> Children(IEnumerable<Person> people)
{
List<Person> result = new List<Person>();
foreach (var person in people)
{
IPersonRelationships personRelationships = FamilyGraph.Get(person);
List<Person> children = personRelationships.Edges.Where(m => m.RelationshipType == RelationshipType.Parent)
.Select(m => m.Target)
.ToList();
result.AddRange(children);
}
return result;
}
public IEnumerable<Person> Siblings(IEnumerable<Person> people)
{
List<Person> result = new List<Person>();
return result;
}
}
}
我想做这样的事情。
var person = new List<Person> {new Person()};
var cousins = person.Parents().Siblings().Children();
我知道当前的实现是不可能的,我可能不得不编写扩展方法。为此,包含扩展方法的类必须是静态的,因此我不能注入 FamilyGraph 依赖项。
如果我返回IBaseRelationships 而不是IEnumerable<Person>,则使用当前的实现,我将能够让它工作。但我不确定如何从中获得实际结果 (IEnumerable<Person>)。
任何关于如何为接口中的方法构建它的想法都会很棒。
编辑。
添加FamilyGraph前参考
public class FamilyGraph : IFamilyGraph
{
private Dictionary<Person, PersonRelationships> Families;
public FamilyGraph(IPersonStore personStore)
{
Families = new Dictionary<Person, PersonRelationships>();
PersonStore = personStore;
}
public IPersonStore PersonStore { get; }
public void Add(EdgeInput inputEdge)
{
Edge edge;
try
{
edge = GetEdge(inputEdge);
}
catch (ArgumentException)
{
throw;
}
switch (edge.RelationshipType)
{
case Enums.RelationshipType.Parent:
AddParentRelationship(edge);
return;
case Enums.RelationshipType.Spouse:
AddSpouseRelationship(edge);
return;
}
}
public Edge GetEdge(EdgeInput inputEdge)
{
Person source, target;
try
{
source = PersonStore.GetPerson(inputEdge.Source);
target = PersonStore.GetPerson(inputEdge.Target);
}
catch (Exception)
{
throw;
}
return new Edge(source, target, inputEdge.RelationshipType);
}
public IPersonRelationships Get(Person person)
{
PersonRelationships personRelationships;
Families.TryGetValue(person, out personRelationships);
return personRelationships;
}
}
public interface IPersonRelationships
{
List<Edge> Edges { get; }
List<Person> Parents { get; }
Person Spouse { get; }
void AddEdge(Edge edge);
void AddParent(Person parent);
void AddSpouse(Person spouse);
bool CanAddParent(Person parent);
}
public interface IPersonStore
{
void Add(Person person);
bool Contains(string personName);
Person GetPerson(string personName);
}
【问题讨论】:
-
什么是 FamlyGraph?它是一家拥有所有关系的商店吗?
-
扩展方法可能是理想的,也许有不同的方式来注入依赖?我讨厌建议使用服务定位器,但它可能会奏效。或者,如果做不到这一点,也许可以按照您的想法返回
IBaseRelationships,然后在返回最终IEnumerable<Person>的接口中再添加一个方法。它限制了流畅的语法,因为一旦调用了最后一个,您就需要在它之后的任何时间启动一个新链,但这可能不会在使用中变得那么糟糕。 -
假设你不能控制 person 和 familygraph 类,引入扩展方法来转换到/从 releasionship 类可能是最简单的,所以它看起来像:person.GetRelationships(familygraph).Parents( ).Siblings().Children().ToPersons() @David - 没有看到你的评论开始,但我相信这本质上也是你的意思。
-
@thebenman
IPersonRelationships?只是公共接口就足够了 -
@AvinKavish 添加
标签: c# fluent method-chaining