我一直有这个问题,一直把头发拉过来。我有以下错误:
异常详细信息:System.NotSupportedException:无法序列化类型System.Collections.Generic.IList`1 [[HannaPrintsDataAccess.CustomerAddress,HannaPrintsDataAccess,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]的成员HannaPrintsDataAccess.Customer.CustomerAddresses ]]因为它是一个界面。
来源错误:
第196行:客户客户= OperationsManager.Instance.CustomerService.GetCustomer(7); 197行: 第198行:字符串xml = OperationsManager.Instance.CustomerService.GetCustomerAddressesXml(CustomerAddress.FindAll()); 199行: 第200行:订单订单= OperationsManager.Instance.OrderService.CreateOrderFromCart(xml);
源文件:c:\ HostingSpaces \ greetwus \ galadavetiye.com \ wwwroot \ HannaPrints \ HannaPrints \ WebUI \ CreateGreetingCard.aspx.cs Line:198
堆栈追踪:
[NotSupportedException:无法序列化类型为System.Collections.Generic.IList`1 [[HannaPrintsDataAccess.CustomerAddress,HannaPrintsDataAccess,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]的成员HannaPrintsDataAccess.Customer.CustomerAddresses,因为它是一个界面。]
[InvalidOperationException:无法序列化'System.Collections.Generic.IList`1类型的成员'HannaPrintsDataAccess.Customer.CustomerAddresses'[[HannaPrintsDataAccess.CustomerAddress,HannaPrintsDataAccess,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null] ]',请参阅内部异常了解更多详情。] System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc,MemberInfo成员,类型类型)+889917 System.Xml.Serialization.StructModel.GetPropertyModel(PropertyInfo propertyInfo)+132 ........
我已经将我的所有IList更改为List's以查看它是否可以执行任何操作,但事实上,在进行这些更改之后它甚至没有花费一秒钟加载,我猜测因为错误发生甚至在它到达之前部分。我检查了我的远程文件,看它是否正确上传,它是。
以下是代码:
using System;
using System.Collections.Generic;
using Castle.ActiveRecord;
namespace HannaPrintsDataAccess {
public partial class Customer {
private IList _customerAddresses;
public CustomerAddress GetPrimaryCustomerAddress()
{
foreach (CustomerAddress address in _customerAddresses)
{
if (address.IsPrimary)
return address;
}
return null;
}
[HasMany(typeof(CustomerAddress), ColumnKey = "CustomerId", Table = "Customer")]
public virtual IList<CustomerAddress> CustomerAddresses
{
get
{
return this._customerAddresses;
}
set
{
this._customerAddresses = value;
}
}
}
}
激活此代码时会发生错误:
protected void orderButton_Click(object sender, EventArgs e)
{
Customer customer = OperationsManager.Instance.CustomerService.GetCustomer(7);
string xml = OperationsManager.Instance.CustomerService.GetCustomerAddressesXml(CustomerAddress.FindAll());
Order order = OperationsManager.Instance.OrderService.CreateOrderFromCart(xml);
OperationsManager.Instance.CartService.MoveCart("MyDesigns");
Response.Redirect("~/Customer/PayByCreditCard.aspx?orderGuid=" + order.OrderGuid);
}
CustomerAddress类:
using System.IO;
using System.Xml.Serialization;
using Castle.ActiveRecord;
namespace HannaPrintsDataAccess
{
public partial class CustomerAddress
{
public string ToXml()
{
XmlSerializer serializer = new XmlSerializer(GetType());
MemoryStream memoryStream = new MemoryStream();
serializer.Serialize(memoryStream, this);
memoryStream.Seek(0, SeekOrigin.Begin);
return new StreamReader(memoryStream).ReadToEnd();
}
[BelongsTo("CustomerId")]
public virtual Customer Customer { get; set; }
}
}
答案 0 :(得分:22)
在您发布的代码中,CustomerAddresses
的类型为IList<CustomerAdress>
。那是一个界面。与错误消息一样,您无法序列化接口。
答案 1 :(得分:1)
在某些情况下,人们可能对序列化对象的所有字段不感兴趣。在这种情况下,从对象的序列化中显式排除字段的 C# 语法如下:
XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
XmlAttributes attrs = new XmlAttributes{ XmlIgnore = true };
attrOverrides.Add(type, member, attrs); // "type" = type of the class that contains the member
XmlSerializer serializer = new XmlSerializer(obj.GetType(), attrOverrides);
[...]
例如,排除,例如出于隐私原因,我们应该编写“obj”对象序列化中的“密码”字段:
attrOverrides.Add(obj.GetType(), "Password", attrs);
对于未在对象中直接声明而是继承的字段,“type”参数指的是声明该字段的祖先。例如,为了避免在 System.ComponentModel.Component 的后代对象中出现错误“无法序列化 System.ComponentModel.ISite 类型的成员 System.ComponentModel.Component.Site,因为它是一个接口 em>",使用的语法是:
attrOverrides.Add(typeof(System.ComponentModel.Component), "Site", attrs);
通常,XMLSerializer 无法序列化暴露接口类型字段的类的对象。然而,如果有人仍然想序列化(使用 XMLSerializer)这种类型的对象(例如出于日志原因)并且在序列化中忽略接口类型的字段没有问题,以下函数会自动忽略这种类型的字段(注意:当然最终结果将不是初始对象的序列化,而是序列化排除被忽略的部分,这不是一回事):
public static string Serialize<T>(T obj, bool ignoreInterfaceTypeFields = false, List<Tuple<Type, string>> ignoreTypeList = null)
{
string retValue = string.Empty;
try
{
XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
XmlAttributes attrs = new XmlAttributes{ XmlIgnore = true };
ignoreTypeList?.ForEach(t => attrOverrides.Add(t.Item1, t.Item2, attrs)); // ignore fields in ignoreTypeList
if (ignoreInterfaceTypeFields)
{
foreach (var t in obj.GetType().GetProperties())
{
if (t.PropertyType.IsInterface)
if (attrOverrides[t.DeclaringType, t.Name] is null)
attrOverrides.Add(t.DeclaringType, t.Name, attrs); // ignore interface type fields
}
}
XmlSerializer serializer = new XmlSerializer(obj.GetType(), attrOverrides);
using (var sw = new StringWriter())
{
using (XmlTextWriter writer = new XmlTextWriter(sw) { Formatting = Formatting.Indented })
{
serializer.Serialize(writer, obj);
retValue = sw.ToString();
}
}
}
catch (Exception ex) { throw ex; }
return retValue;
}
// declared in non-generic, non-nested static classes
public static string Serialize<T>(this T obj, bool ignoreInterfaceTypeFields = false, List<Tuple<Type, string>> ignoreTypeList = null)
{
return Serialize<T>(obj, ignoreInterfaceTypeFields, ignoreTypeList);
}
这个Serialize方法可以不带参数调用:
sClient = client.Serialize();
或手动排除不需要的字段:
var ignoreTypeList = new List<Tuple<Type, string>>
{
new Tuple<Type, string>(client.GetType(), "Password"), // unwanted field (directly declared in "Client" class)
new Tuple<Type, string>(typeof(System.ComponentModel.Component), "Site") // unwanted field (declared in "System.ComponentModel.Component" ancestor class of "Client" class)
};
sClient = client.Serialize(false, ignoreTypeList);
或排除不需要的字段和接口类型字段:
var ignoreTypeList = new List<Tuple<Type, string>>
{
new Tuple<Type, string>(client.GetType(), "Password") // unwanted field (directly declared in "Client" class)
};
sClient = client.Serialize(true, ignoreTypeList);
注意:使用框架 4.7.2 或更高版本(或使用 System.ValueTuple nuget)可以使元组的语法更具可读性:
public static string Serialize<T>(T obj, bool ignoreInterfaceTypeFields = false, List<(Type type, string member)> ignoreTypeList = null)
和:
var ignoreTypeList = new List<(Type, string)>
{
new (client.GetType(), "Password"),
new (typeof(System.ComponentModel.Component), "Site")
};
答案 2 :(得分:0)
以下选项因 XML 序列化程序失败:
public IList<CustomerAddresses> CustomerAddresses { get; set; }
public IEnumerable<CustomerAddresses> CustomerAddresses { get; set; }
使用如下数组:
public CustomerAddresses[] CustomerAddresses { get; set; }
以下作品但不是声纳/质量投诉:
public List<CustomerAddresses> CustomerAddresses { get; set; }
答案 3 :(得分:-1)
不是您的问题的根源,但您需要
using (MemoryStream memoryStream = new MemoryStream())
{
serializer.Serialize(memoryStream, this);
memoryStream.Seek(0, SeekOrigin.Begin);
using (StreamReader reader = new StreamReader(memoryStream))
{
return reader.ReadToEnd();
}
}