Хороший вопрос - и трудно разобраться, я думаю, что у меня есть - хотя - это, вероятно, не самый производительный.
Как вы говорите, проблема заключается в нескольких типах - поэтому давайте настроим все, я использую метод расширения, чтобы сделать этот код более привлекательным:
public static class Extensions
{
public static T ToObject<T>(this string value)
{
//deserialize into a 'Node' first
var node = JsonConvert.DeserializeObject<Node>(value);
//then take the 'data' from that and 'ToObject' to the correct thing.
return ((JObject) node.data).ToObject<T>();
}
private class Node{
public object data {get;set;}
}
}
The * Метод 1006 * - это то, что мы будем использовать для преобразования нашего вывода в объекты.
У меня есть стандартный набор POCO для представления данных (хотя и с неправильными соглашениями об именах для свойств):
public class Movie {
public string title {get;set;}
public string tagline {get;set;}
}
public class Person {
public string name {get;set;}
public int born {get;set;}
}
public class RolesRel {
public IEnumerable<string> roles {get;set;}
}
ОК - теперь мы готовы к go. Я изменил Return
, чтобы он выглядел так:
var shortestPath = graphClient.Cypher
.OptionalMatch("p = shortestPath((bacon: Person)-[*]-(meg: Person ) )")
.Where((Person bacon) => bacon.name == "Kevin Bacon")
.AndWhere((Person meg) => meg.name == "Meg Ryan")
.Return(p => new {
Nodes = Return.As<IEnumerable<string>>("nodes(p)"),
Relationships = Return.As<IEnumerable<RolesRel>>("rels(p)")
});
string
- это единственная универсальная опция, которую мы получили для десериализации нескольких типов узлов. В этом сценарии, поскольку отношения все одинаковы, мы все хорошо на этом фронте просто используем POCO - но если бы они не были, вы бы в конечном итоге сделали то же, что мы делаем для узлов для них.
Далее я просматриваю результаты:
foreach (var result in shortestPath.Results)
{
foreach (var node in result.Nodes)
{
if(node.Contains("name"))
Console.WriteLine(node.ToObject<Person>().name);
else if(node.Contains("title"))
Console.WriteLine(node.ToObject<Movie>().title);
else {
Console.WriteLine("Unknown Node Type: " + node);
}
}
}
Здесь я делаю наивную проверку для имени свойства, которое, как мне известно, относится к одному типу узла, но не к другому - и вы можете хочу сделать это по-другому - но это работает.
Очевидно - я просто выводлю на экран - но у вас будет доступ к самому объекту.