ServiceStack.Text 序列化异常(为调用方法“Void set_Item(Int32, MyApp.MyClass)”提供的参数数量不正确)
我正在尝试使用 ServiceStack.Text 反序列化包含嵌套类列表的对象。
序列化进行得很顺利,但是当尝试反序列化时,我收到此错误:
System.TypeInitializationException:类型初始值设定项 “ServiceStack.Text.Jsv.JsvReader
1”引发异常。 ---> System.TypeInitializationException:类型初始值设定项 “ServiceStack.Text.Jsv.JsvReader
1”引发异常。 ---> System.TypeInitializationException:类型初始值设定项 “ServiceStack.Text.Common.DeserializeList2”引发异常。 ---> System.TypeInitializationException:类型初始值设定项 “ServiceStack.Text.Jsv.JsvReader
1”引发异常。 ---> System.TypeInitializationException:类型初始值设定项 “ServiceStack.Text.Jsv.JsvReader1”引发异常。 ---> System.TypeInitializationException:类型初始值设定项 “ServiceStack.Text.Common.DeserializeList
2”引发异常。 ---> System.TypeInitializationException:类型初始值设定项 “ServiceStack.Text.Jsv.JsvReader`1”引发异常。 ---> System.ArgumentException:提供的参数数量不正确 调用方法“Void set_Item(Int32, MyApp.MyClass)”
我的解决方案中没有名为 set_Item 的方法,我也无法在 ServiceStack.Text 程序集中找到这样命名的方法(使用反射器)。我不知道问题可能是什么......而且我需要一个快速序列化类型,但我知道最快的序列化类型(protobuf-net)不支持嵌套列表。
有什么想法吗?导致问题的类如下(原型成员在那里,因为我测试了 protobuf 方法)
[Serializable]
/// <summary>
/// Description of Livres.
/// </summary>
public class Livres : IEnumerable<Livre>
{
[ProtoMember(1)]
private List<Livre> listeLivres;
public List<Livre> ListeLivres
{
get { return listeLivres; }
set { listeLivres = value; }
}
public List<string> NomLivres
{
get
{
List<string> lst = new List<string>();
foreach (Livre livre in this.listeLivres)
{
lst.Add(livre.NomLivre);
}
return lst;
}
}
public int Count
{
get
{
return ((this.listeLivres != null) ? this.listeLivres.Count : 0);
}
}
public Livre this[string nomLivre]
{
get
{
nomLivre = nomLivre.ToLower();
if (nomLivre == "")
{
return null;
}
try
{
var u = this.listeLivres.Single(book => book.NomLivre.ToLower() == nomLivre);
return u;
}
catch (InvalidOperationException)
{
string pattern = "^[0-9][a-zA-Z]+$";
Regex reg = new Regex(pattern);
if (reg.IsMatch(nomLivre))
{
string nom = nomLivre[0].ToString() + " ";
nom += nomLivre.Substring(1).ToLower();
try
{
var u = this.listeLivres.Single(book => book.NomLivre.ToLower() == nom);
return u;
}
catch (Exception)
{
return null;
}
}
else
return null;
}
}
set
{
if (nomLivre == "")
{
throw new
ArgumentNullException("L'index ne doit pas être une chaine vide.");
}
try
{
Livre liv = this.listeLivres.Single(book => book.NomLivre == nomLivre);
liv = value;
}
catch (InvalidOperationException ex)
{
string pattern = "^[0-9][a-zA-Z]+$";
Regex reg = new Regex(pattern);
if (reg.IsMatch(nomLivre))
{
string nom = nomLivre[0].ToString() + " ";
nom += nomLivre.Substring(1);
try
{
Livre L = this.listeLivres.Single(book => book.NomLivre == nom);
L = value;
}
catch (Exception e)
{
throw new ArgumentException("Ce nom de livre n'existe pas dans la liste", e);
}
}
else
throw new ArgumentException("Ce nom de livre n'existe pas dans la liste", ex);
}
}
}
/// <summary>
/// Obtient ou définit le Livre à l'index spécifié - 1
/// Exceptions:
/// ArgumentOutOfRangeException
/// </summary>
public Livre this[int index]
{
get
{
if (index < 1 || index > this.listeLivres.Count)
{
throw new
ArgumentOutOfRangeException("L'index spécifié n'était pas correct");
}
return this.listeLivres[index-1];
}
set
{
if (index < 1 || index > this.listeLivres.Count)
{
throw new
ArgumentOutOfRangeException("L'index spécifié n'était pas correct");
}
this.listeLivres[index - 1] = value;
}
}
#region Constructeurs
public Livres()
{
this.listeLivres = new List<Livre>();
}
public Livres(Livre livre)
: this()
{
this.listeLivres.Add(livre);
}
#endregion
/// <summary>
/// Retourne le verset correspondant si il existe, sinon null
/// Exceptions
/// ArgumentException
/// </summary>
/// <param name="referenceComplete">La référence du verset sous forme de chaine (ex: "1 Jean 5:19")</param>
public Verset GetVerset(string referenceComplete)
{
if (string.IsNullOrWhiteSpace(referenceComplete))
return null;
string[] tab = referenceComplete.Split();
try
{
string livre = "";
int chapitre;
int verset;
if (tab.Length>2)
{
livre = tab[0];
}
livre += tab[tab.Length -2];
string [] tabVerse = tab[tab.Length -1].Split(':');
chapitre = Convert.ToInt32(tabVerse[0]);
verset = Convert.ToInt32(tabVerse[1]);
return this[livre][chapitre][verset];
}
catch (Exception ex)
{
throw new ArgumentException("Il n'y a aucun verset avec cette référence",ex);
}
}
public void Add(Livre livre)
{
this.listeLivres.Add(livre);
}
public static Livres operator +(Livres livres, Livre livre)
{
livres.Add(livre);
return livres;
}
public IEnumerator<Livre> GetEnumerator()
{
foreach (Livre item in this.listeLivres)
{
yield return item;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public void Serialize(string pathName= "BibleData.txt")
{
try
{
#region ServiceStack Serializer
TextWriter tw = new StreamWriter(pathName);
TypeSerializer<Livres> TypeSrlzr = new TypeSerializer<Livres>();
TypeSrlzr.SerializeToWriter(this,tw);
//TypeSerializer.SerializeToWriter(this,tw);
tw.Close();
#endregion
}
catch (Exception)
{
throw;
}
}
public static Livres Deserialize(string pathName= "BibleData.txt")
{
try
{
Livres Bible;
#region ServiceStack Deserializer
TextReader tr = new StreamReader(pathName);
TypeSerializer<Livres> typeSrlzr = new TypeSerializer<Livres>();
Bible = typeSrlzr.DeserializeFromReader(tr);
//Bible = TypeSerializer<Livres>.DeserializeFromReader(tr);
#endregion
return Bible;
}
catch (Exception) {
throw;
}
}
}
I am trying to deserialize an object that contains nested lists of classes with ServiceStack.Text.
The serialization went well, but when trying to deserialize, I get this error:
System.TypeInitializationException: The type initializer for
'ServiceStack.Text.Jsv.JsvReader1' threw an exception. --->
1' threw an exception. --->
System.TypeInitializationException: The type initializer for
'ServiceStack.Text.Jsv.JsvReader
System.TypeInitializationException: The type initializer for
'ServiceStack.Text.Common.DeserializeList2' threw an exception. --->
1' threw an exception. --->
System.TypeInitializationException: The type initializer for
'ServiceStack.Text.Jsv.JsvReader
System.TypeInitializationException: The type initializer for
'ServiceStack.Text.Jsv.JsvReader1' threw an exception. --->
2' threw an exception. --->
System.TypeInitializationException: The type initializer for
'ServiceStack.Text.Common.DeserializeList
System.TypeInitializationException: The type initializer for
'ServiceStack.Text.Jsv.JsvReader`1' threw an exception. --->
System.ArgumentException: Incorrect number of arguments supplied for
call to method 'Void set_Item(Int32, MyApp.MyClass)'
I have no method named set_Item in my solution, neither can I find a method named like this in the ServiceStack.Text assembly (using reflector). I have no clue of what the problem could be...And I need a fast serialization type, but the fastest I know(protobuf-net) doesn't support nested lists.
Any ideas? The class that caused the problem is below (the protomembers are there because I tested the protobuf method)
[Serializable]
/// <summary>
/// Description of Livres.
/// </summary>
public class Livres : IEnumerable<Livre>
{
[ProtoMember(1)]
private List<Livre> listeLivres;
public List<Livre> ListeLivres
{
get { return listeLivres; }
set { listeLivres = value; }
}
public List<string> NomLivres
{
get
{
List<string> lst = new List<string>();
foreach (Livre livre in this.listeLivres)
{
lst.Add(livre.NomLivre);
}
return lst;
}
}
public int Count
{
get
{
return ((this.listeLivres != null) ? this.listeLivres.Count : 0);
}
}
public Livre this[string nomLivre]
{
get
{
nomLivre = nomLivre.ToLower();
if (nomLivre == "")
{
return null;
}
try
{
var u = this.listeLivres.Single(book => book.NomLivre.ToLower() == nomLivre);
return u;
}
catch (InvalidOperationException)
{
string pattern = "^[0-9][a-zA-Z]+$";
Regex reg = new Regex(pattern);
if (reg.IsMatch(nomLivre))
{
string nom = nomLivre[0].ToString() + " ";
nom += nomLivre.Substring(1).ToLower();
try
{
var u = this.listeLivres.Single(book => book.NomLivre.ToLower() == nom);
return u;
}
catch (Exception)
{
return null;
}
}
else
return null;
}
}
set
{
if (nomLivre == "")
{
throw new
ArgumentNullException("L'index ne doit pas être une chaine vide.");
}
try
{
Livre liv = this.listeLivres.Single(book => book.NomLivre == nomLivre);
liv = value;
}
catch (InvalidOperationException ex)
{
string pattern = "^[0-9][a-zA-Z]+$";
Regex reg = new Regex(pattern);
if (reg.IsMatch(nomLivre))
{
string nom = nomLivre[0].ToString() + " ";
nom += nomLivre.Substring(1);
try
{
Livre L = this.listeLivres.Single(book => book.NomLivre == nom);
L = value;
}
catch (Exception e)
{
throw new ArgumentException("Ce nom de livre n'existe pas dans la liste", e);
}
}
else
throw new ArgumentException("Ce nom de livre n'existe pas dans la liste", ex);
}
}
}
/// <summary>
/// Obtient ou définit le Livre à l'index spécifié - 1
/// Exceptions:
/// ArgumentOutOfRangeException
/// </summary>
public Livre this[int index]
{
get
{
if (index < 1 || index > this.listeLivres.Count)
{
throw new
ArgumentOutOfRangeException("L'index spécifié n'était pas correct");
}
return this.listeLivres[index-1];
}
set
{
if (index < 1 || index > this.listeLivres.Count)
{
throw new
ArgumentOutOfRangeException("L'index spécifié n'était pas correct");
}
this.listeLivres[index - 1] = value;
}
}
#region Constructeurs
public Livres()
{
this.listeLivres = new List<Livre>();
}
public Livres(Livre livre)
: this()
{
this.listeLivres.Add(livre);
}
#endregion
/// <summary>
/// Retourne le verset correspondant si il existe, sinon null
/// Exceptions
/// ArgumentException
/// </summary>
/// <param name="referenceComplete">La référence du verset sous forme de chaine (ex: "1 Jean 5:19")</param>
public Verset GetVerset(string referenceComplete)
{
if (string.IsNullOrWhiteSpace(referenceComplete))
return null;
string[] tab = referenceComplete.Split();
try
{
string livre = "";
int chapitre;
int verset;
if (tab.Length>2)
{
livre = tab[0];
}
livre += tab[tab.Length -2];
string [] tabVerse = tab[tab.Length -1].Split(':');
chapitre = Convert.ToInt32(tabVerse[0]);
verset = Convert.ToInt32(tabVerse[1]);
return this[livre][chapitre][verset];
}
catch (Exception ex)
{
throw new ArgumentException("Il n'y a aucun verset avec cette référence",ex);
}
}
public void Add(Livre livre)
{
this.listeLivres.Add(livre);
}
public static Livres operator +(Livres livres, Livre livre)
{
livres.Add(livre);
return livres;
}
public IEnumerator<Livre> GetEnumerator()
{
foreach (Livre item in this.listeLivres)
{
yield return item;
}
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public void Serialize(string pathName= "BibleData.txt")
{
try
{
#region ServiceStack Serializer
TextWriter tw = new StreamWriter(pathName);
TypeSerializer<Livres> TypeSrlzr = new TypeSerializer<Livres>();
TypeSrlzr.SerializeToWriter(this,tw);
//TypeSerializer.SerializeToWriter(this,tw);
tw.Close();
#endregion
}
catch (Exception)
{
throw;
}
}
public static Livres Deserialize(string pathName= "BibleData.txt")
{
try
{
Livres Bible;
#region ServiceStack Deserializer
TextReader tr = new StreamReader(pathName);
TypeSerializer<Livres> typeSrlzr = new TypeSerializer<Livres>();
Bible = typeSrlzr.DeserializeFromReader(tr);
//Bible = TypeSerializer<Livres>.DeserializeFromReader(tr);
#endregion
return Bible;
}
catch (Exception) {
throw;
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您不想从 IEnumerable 继承,因为它不太可能按照您期望的方式运行。即所有 Enumerables 都像 JSON 数组/集合一样序列化,并且附加属性将被忽略。
仅具有 IEnumerable 接口的问题是无法通用地填充它。因此,虽然您可能能够序列化它,但您将无法反序列化它。
如果您实现的集合接口还提供了填充功能,即 IList 或 ICollection ,您将会更加成功。
You don't want to inherit from an IEnumerable as it will not likely behave in the way you expect. i.e. all Enumerables are serialized like a JSON Array/Collection and the additional properties are ignored.
The problem with only having an IEnumerable interface is that there is no way to generically populate it. So whilst you may be able to serialize it, you won't be able to deserialize it.
You would be more successful if you implemented a collection interface that also provides an ability to populate it, i.e. IList<T> or ICollection<T>.
我也有同样的问题。我需要我的类继承 IDataErrorInfo,问题出在索引属性中。不过,您可以在源代码中自行修复它。在 OrmLiteConfigExtensions 中找到方法 GetModelDefinition 并查找:
GetValueFn = propertyInfo.GetPropertyGetterFn(),
SetValueFn = propertyInfo.GetPropertySetterFn(),
仅将 GetValueFn 行替换为:
GetValueFn = (propertyInfo.GetIndexParameters().Length == 0)?null:propertyInfo.GetPropertyGetterFn(),
这样它将跳过为索引属性设置 GetValueFn 属性这会引发异常。
I had the same problem. I needed my classes to inherit IDataErrorInfo, and the problem is in the indexed property. You can fix it yourself in the source code though. In the OrmLiteConfigExtensions find the method GetModelDefinition and look for:
GetValueFn = propertyInfo.GetPropertyGetterFn(),
SetValueFn = propertyInfo.GetPropertySetterFn(),
replace the GetValueFn line only with:
GetValueFn = (propertyInfo.GetIndexParameters().Length == 0)?null:propertyInfo.GetPropertyGetterFn(),
This way it will skip setting the GetValueFn property for indexed properties which throws the exception.