从 Gremlin.Net 回复中获取 POCO 的最佳方式是什么?
现在我手动转换到字典:
var results = await gremlinClient.SubmitAsync<Dictionary<string, object>>("g.V()");
var result = results[0];
var properties = (Dictionary<string, object>)result["properties"];
var value = ((Dictionary<string, object>)properties["myValue"].Single())["value"];
我发现
GremlinClient
只能返回动态对象,如果你将其他任何东西作为类型,它就会失败(除非我只是做错了什么)。
我最终所做的是将动态对象序列化为 JSON,然后将其反序列化回我想要的对象类型:
var results = await gremlinClient.SubmitAsync<dynamic>("g.V()");
JsonConvert.DeserializeObject<MyResult>(JsonConvert.SerializeObject(results));
动态对象只是一个字典,但如果您首先序列化它,它就会具有适当的字段/属性层次结构,然后可以将其反序列化为您实际期望的内容。
必须进行额外的转换似乎有点痛苦,但这是我让它发挥作用的唯一方法。
您可以使用类似于
的MyClass来获取您的属性 class ProviderProperties {
public object Name { get; set; }
public object contact { get; set; }
public object requesttype { get; set; }
public object address { get; set; }
public object phone { get; set; }
public object description { get; set; }
public object otherState { get; set; }
public object otherCity { get; set; }
public object addressStreet { get; set; }
}
class MyClass {
public string id { get; set; }
public string label { get; set; }
public string type { get; set; }
public ProviderProperties properties { get; set; }
}
并将其用于
JsonConvert.DeserializeObject<MyClass>(JsonConvert.SerializeObject(results));
尝试这个方法
IGremlinClient janusClient = JanusGraphClientBuilder.BuildClientForServer(new GremlinServer("localhost", 8182)).Create();
GraphTraversalSource g = Traversal().WithRemote(new DriverRemoteConnection(janusClient));
IList<Vertex> x = g.V().HasLabel("YourLabel").Has("YourpPopertyName", "some value").ToList();
由于 Gremlin.NET 的响应是 JSON,如嵌套的 Dictionary
ICharacter character=new DictionaryAdapterFactory().GetAdapter<ICharacter>(response)
//use as
//character.goals[0].description
public interface ICharacter:IElement
{
[DictionaryAdapter(typeof(ICharacterProperties))]
ICharacterProperties properties { get; set; }
[ListOfDictionariesAdapter(typeof(List<IGoal>))]
List<IGoal> goals { get; set; }
}
public interface IElement
{
string label { get; set; }
long id { get; set; }
}
public interface IGoal
{
string description { get; set; }
}
...other interfaces
您需要编写 2 个属性来处理嵌套字典和字典列表。
using System;
using System.Collections;
using Castle.Components.DictionaryAdapter;
namespace x
{
public class DictionaryAdapterAttribute : DictionaryBehaviorAttribute,
IPropertyDescriptorInitializer, IDictionaryPropertyGetter
{
private Type __type;
public DictionaryAdapterAttribute(Type type)
{
__type = type;
}
public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue,
PropertyDescriptor property, bool ifExists)
{
if (storedValue != null && storedValue.GetType().IsGenericType &&
storedValue is IDictionary dictionary)
{
var adapter = dictionaryAdapter.Meta.Factory.GetAdapter(__type,
dictionary);
dictionaryAdapter.SetProperty(key, ref adapter);
}
return storedValue;
}
public void Initialize(PropertyDescriptor propertyDescriptor, object[] behaviors)
{
propertyDescriptor.Fetch = true;
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using Castle.Components.DictionaryAdapter;
namespace X
{
/// <summary>
/// will convert List<Dictionaries> to List<of addapters of Dictionaries>(default) or some other Collection Class
/// which should have constructor accepting IEnumerable
/// </summary>
public class ListOfDictionariesAdapterAttribute : DictionaryBehaviorAttribute,
IPropertyDescriptorInitializer, IDictionaryPropertyGetter
{
private Type __type;
private bool __adapted;
public ListOfDictionariesAdapterAttribute(Type type)
{
__type = type;
}
public object GetPropertyValue(IDictionaryAdapter dictionaryAdapter, string key, object storedValue,
PropertyDescriptor property, bool ifExists)
{
// var o = dictionaryAdapter.GetProperty(key, ifExists);
if (!__adapted && storedValue != null && storedValue.GetType().IsGenericType &&
storedValue is IEnumerable enumerable)
{
if (enumerable.GetType().GetGenericArguments()[0] != __type)
{
var enumerator = enumerable.GetEnumerator();
var genericArgument = __type.GetGenericArguments()[0];
IList ilistWrapper =
Activator.CreateInstance(typeof(List<>).MakeGenericType(genericArgument)) as IList;
while (enumerator.MoveNext())
{
if (enumerator.Current is IDictionary current)
ilistWrapper?.Add(dictionaryAdapter.Meta.Factory.GetAdapter(genericArgument,
current));
}
object list;
if (__type.GetGenericTypeDefinition()==typeof(List<>))
{
//instead of List<Dictionaries> swap with List<adapters of Dictionaries>
list = ilistWrapper;
}
else
{
//!! Note maybe use https://github.com/GriffinPlus/dotnet-libs-fastactivator instead of
//collection must have constructor that accept enumerable as params
list = Activator.CreateInstance(__type, ilistWrapper);
//v2 only for ObservableLinkedList,List
// var methodInfo = list.GetType().GetMethod("AddLast",new Type[]{genericArgument});
//
// enumerator.Reset();
//
// while (enumerator.MoveNext())
// {
// var adapter = dictionaryAdapter.Meta.Factory.GetAdapter(genericArgument,
// (IDictionary) enumerator.Current);
// methodInfo?.Invoke(list,new object[]{adapter});
// }
}
dictionaryAdapter.SetProperty(key, ref list);
__adapted = true;
}
}
return storedValue;
}
public void Initialize(PropertyDescriptor propertyDescriptor, object[] behaviors)
{
propertyDescriptor.Fetch = true;
}
}
}