无法序列化成员<x>,因为它是一个接口

时间:2015-07-25 20:06:46

标签: c# asp.net deserialization xml-serialization neo4jclient

关注Error with explicit conversion when using CollectAs<>

中的问题

来自WebMethod的代码

return client.Cypher
        .Match("(person:Person)")
        .Where((Person person) => person.Email == username)
        .OptionalMatch("(person)-[:SPEAKS]-(language:Language)")
        .OptionalMatch("(person)-[:CURRENT_LOCATION]-(country:Country)"
        .Return((person, language, country) => new ProfileObject
        {
            Person = person.As<Person>(),
            Language = language.CollectAs<Language>(),
            Country = country.CollectAs<Country>()
        }).Results.ToList();

国家/地区类代码:

public class Language
{
    public string Name { get; set; }
}

ProfileObject类的新代码:

public class ProfileObject
{
    public Person Person { get; set; }
    public IEnumerable<Node<Language>> Language { get; set; }
    public IEnumerable<Node<Country>> Country { get; set; }
}

只有当我将ProfileObject设置为返回IEnumerable&gt;时才会出现此错误,如果我将其返回到

public Country Country {get; set;} 

然后它可以工作(但我显然会为每个返回的Country对象获得重复的Person条目。

任何人都能告诉我这个问题的解决方案并不会让我把所有代码都删掉并重新开始吗?

更新

  

[InvalidOperationException:Neo4jClient.Node`1 [Graph.Language]无法序列化,因为它没有无参数构造函数。]

     

[InvalidOperationException:无法序列化成员&#39; Graph.ProfileObject.Language&#39;类型&#39; System.Collections.Generic.List 1[[Neo4jClient.Node 1 [[Graph.Language,Graph,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],Neo4jClient,Version = 0.0.0.0 ,Culture = neutral,PublicKeyToken = null]]&#39;,请参阅内部异常以获取更多详细信息。      System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc,MemberInfo成员,类型类型)+5451673      System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc,MemberInfo成员,类型类型)+69      System.Xml.Serialization.StructModel.GetPropertyModel(PropertyInfo propertyInfo)+125      System.Xml.Serialization.StructModel.GetFieldModel(MemberInfo memberInfo)+89      System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping,StructModel model,Boolean openModel,String typeName,RecursionLimiter limiter)+618      System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model,String ns,Boolean openModel,XmlAttributes a,RecursionLimiter limiter)+378      System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model,String ns,ImportContext context,String dataType,XmlAttributes a,Boolean repeats,Boolean openModel,RecursionLimiter limiter)+1799

     

[InvalidOperationException:反映类型错误&#39; Graph.ProfileObject&#39;。]      System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model,String ns,ImportContext context,String dataType,XmlAttributes a,Boolean repeats,Boolean openModel,RecursionLimiter limiter)+1917      System.Xml.Serialization.XmlReflectionImporter.CreateArrayElementsFromAttributes(ArrayMapping arrayMapping,XmlArrayItemAttributes attributes,Type arrayElementType,String arrayElementNs,RecursionLimiter limiter)+263      System.Xml.Serialization.XmlReflectionImporter.ImportArrayLikeMapping(ArrayModel model,String ns,RecursionLimiter limiter)+264      System.Xml.Serialization.XmlReflectionImporter.ImportAccessorMapping(MemberMapping accessor,FieldModel model,XmlAttributes a,String ns,Type choiceIdentifierType,Boolean rpc,Boolean openModel,RecursionLimiter limiter)+5456308      System.Xml.Serialization.XmlReflectionImporter.ImportMemberMapping(XmlReflectionMember xmlReflectionMember,String ns,XmlReflectionMember [] xmlReflectionMembers,Boolean rpc,Boolean openModel,RecursionLimiter limiter)+852      System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember [] xmlReflectionMembers,String ns,Boolean hasWrapperElement,Boolean rpc,Boolean openModel,RecursionLimiter limiter)+286

     

[InvalidOperationException:有一个错误反映了&#39; MyResult&#39;。]      System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(XmlReflectionMember [] xmlReflectionMembers,String ns,Boolean hasWrapperElement,Boolean rpc,Boolean openModel,RecursionLimiter limiter)+979      System.Xml.Serialization.XmlReflectionImporter.ImportMembersMapping(String elementName,String ns,XmlReflectionMember [] members,Boolean hasWrapperElement,Boolean rpc,Boolean openModel,XmlMappingAccess access)+133      System.Web.Services.Protocols.SoapReflector.ImportMembersMapping(XmlReflectionImporter xmlImporter,SoapReflectionImporter soapImporter,Boolean serviceDefaultIsEncoded,Boolean rpc,SoapBindingUse use,SoapParameterStyle paramStyle,String elementName,String elementNamespace,Boolean nsIsDefault,XmlReflectionMember [] members,Boolean validate,Boolean openModel, String key,Boolean writeAccess)+240      System.Web.Services.Protocols.SoapReflector.ReflectMethod(LogicalMethodInfo methodInfo,Boolean client,XmlReflectionImporter xmlImporter,SoapReflectionImporter soapImporter,String defaultNs)+2893

     

[InvalidOperationException:Method ProfileServices.My无法反映。]      System.Web.Services.Protocols.SoapReflector.ReflectMethod(LogicalMethodInfo methodInfo,Boolean client,XmlReflectionImporter xmlImporter,SoapReflectionImporter soapImporter,String defaultNs)+6173      System.Web.Services.Description.SoapProtocolReflector.ReflectMethod()+137      System.Web.Services.Description.ProtocolReflector.ReflectBinding(ReflectedBinding reflectBinding)+1776      System.Web.Services.Description.ProtocolReflector.Reflect()+641      System.Web.Services.Description.ServiceDescriptionReflector.ReflectInternal(ProtocolReflector [] reflectors)+685      System.Web.Services.Description.ServiceDescriptionReflector.Reflect(Type type,String url)+118      System.Web.Services.Protocols.DocumentationServerType..ctor(Type type,String uri,Boolean excludeSchemeHostPortFromCachingKey)+230      System.Web.Services.Protocols.DocumentationServerProtocol.Initialize()+ 434      System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type,HttpContext context,HttpRequest request,HttpResponse response,Boolean&amp; abortProcessing)+122

     

[InvalidOperationException:无法处理请求。]      System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type,HttpContext context,HttpRequest request,HttpResponse response,Boolean&amp; abortProcessing)+320      System.Web.Services.Protocols.WebServiceHandlerFactory.CoreGetHandler(Type type,HttpContext context,HttpRequest request,HttpResponse response)+171

     

[InvalidOperationException:无法处理请求。]      System.Web.Services.Protocols.WebServiceHandlerFactory.CoreGetHandler(Type type,HttpContext context,HttpRequest request,HttpResponse response)+374      System.Web.Services.Protocols.WebServiceHandlerFactory.GetHandler(HttpContext context,String verb,String url,String filePath)+209      System.Web.Script.Services.ScriptHandlerFactory.GetHandler(HttpContext context,String requestType,String url,String pathTranslated)+48      System.Web.HttpApplication.MapHttpHandler(HttpContext context,String requestType,VirtualPath path,String pathTranslated,Boolean useAppConfig)+226      System.Web.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()+ 145      System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean&amp; completedSynchronously)+155

2 个答案:

答案 0 :(得分:3)

默认情况下,使用DataContractSerializer序列化为XML,但错误消息"Cannot serialize member <x> because it is an interface"generated by XmlSerializer,因此显然您已切换到该值。

您可以考虑切换回指定hereDataContractSerializer,只要基础类型IEnumerable<T>可以序列化,就可以序列化T类型的属性。

或者,如果您不想这样做,您可以修改ProfileObject类以返回代理数组以进行序列化,而无需更改基础设计:

public class ProfileObject
{
    public Person Person { get; set; }

    [XmlIgnore]
    public IEnumerable<Node<Language>> Language { get; set; }

    [XmlIgnore]
    public IEnumerable<Node<Country>> Country { get; set; }

    [XmlArray("Languages")]
    [XmlArrayItem("Language")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public Node<Language>[] LanguageArray
    {
        get
        {
            if (Language == null)
                return null;
            return Language.ToArray();
        }
        set
        {
            Language = value;
        }
    }

    [XmlArray("Countries")]
    [XmlArrayItem("Country")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public Node<Country>[] CountryArray
    {
        get
        {
            if (Country == null)
                return null;
            return Country.ToArray();
        }
        set
        {
            Country = value;
        }
    }
}

<强>更新

XmlSerializer只会使用公开getset方法序列化属性。由于Node.Data仅限get,因此无法按XmlSerializer序列化。

由于您只需序列化数据而不需要Node<TData>,并且永远不需要反序列化,您可以使用linq将您的可枚举节点转换为用于序列化的数据数组,如下所示:

public static class NodeExtensions
{
    public static TData [] ToDataArray<TData>(this IEnumerable<Node<TData>> nodes)
    {
        if (nodes == null)
            return null;
        return nodes.Select(n => n.Data).ToArray();
    }
}

public class ProfileObject
{
    public Person Person { get; set; }

    [XmlIgnore]
    public IEnumerable<Node<Language>> Language { get; set; }

    [XmlIgnore]
    public IEnumerable<Node<Country>> Country { get; set; }

    [XmlArray("ArrayOfLanguage")]
    [XmlArrayItem("Language")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public Language [] LanguageArray
    {
        get
        {
            return Language.ToDataArray();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    [XmlArray("ArrayOfCountry")]
    [XmlArrayItem("Country")]
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DebuggerBrowsable(DebuggerBrowsableState.Never)]
    public Country [] CountryArray
    {
        get
        {
            return Country.ToDataArray();
        }
        set
        {
            throw new NotImplementedException();
        }
    }
}

答案 1 :(得分:1)

因此,您不需要向Node<T>类添加任何更改,它应该将所有内容反序列化。

所以,这是我目前的设置:

public class Country
{
    public string Name { get; set; }
}

public class Language
{
    public string Name { get; set; }
}

public class ProfileObject
{
    public Person Person { get; set; }
    public IEnumerable<Node<Language>> Language { get; set; }
    public IEnumerable<Node<Country>> Country { get; set; }
}

public class Person
{
    public int Id { get; set; }
    public string Email { get; set; }
}

你没有定义CountryPerson所以我已经制定了它们,但实质上我觉得它非常接近。现在我将我的数据库初始化为:

(PERSON)-[:SPEAKS]->(ENGLISH)
(PERSON)-[:SPEAKS]->(GERMAN)
(PERSON)-[:CURRENT_LOCATION]->(GERMANY)

首先,按原样运行查询&#39; (即直接从此页面复制)在序列化方面对我来说很好用 - 您能否确认您的LanguagePersonCountryProfileObject和您一样# 39; ve定义了默认构造函数还是显式无参数构造函数?

关于你期待什么 - 我想你是在ProfileObject之后拥有2个Language个对象,而且只有1 Country。现在,您编写的查询将转换为Cypher,如下所示:

MATCH (person:Person)
WHERE (person.Email = "THE EMAIL ADDRESS HERE")
OPTIONAL MATCH (person)-[:SPEAKS]-(language:Language)
OPTIONAL MATCH (person)-[:CURRENT_LOCATION]-(country:Country)
RETURN person AS Person, collect(language) AS Language, collect(country) AS Country

如果你在Neo4j管理器(localhost:7474)中运行它并切换到&#39;行&#39;查看(从图表中)您将看到您实际上以您在客户端中获得的形式返回数据。

我会在neo4j管理视图中调整查询,直到得到你想要的结果。之后可能不值得返回CollectAs并执行LINQ .Group