C# 反序列化GenericObject列表<;T>;形形色色
我的最终目标是存储一些用于生成用于报告的SQL的参数,以减少(或删除?)SQL注入的可能性 因此,在我的解决方案中,我计划在我的应用程序的管理面板中创建一个报告定义。报表定义是用于生成输出的原始SQL,然后有一个参数定义要在UI中呈现给用户,并尝试保持强类型 这些参数就是我目前遇到的问题。我可以正确地序列化参数列表,XML看起来像我期望的那样,但在某些异常情况下尝试反序列化结果 我尝试构建一个简单的方法,将XML字符串转换为对象,并得到了一些支持。我理解异常和原因,只是不知道如何解决 当我尝试反序列化泛型对象时,它失败了。在Xml中,泛型可能如下所示:C# 反序列化GenericObject列表<;T>;形形色色,c#,xml,xml-serialization,C#,Xml,Xml Serialization,我的最终目标是存储一些用于生成用于报告的SQL的参数,以减少(或删除?)SQL注入的可能性 因此,在我的解决方案中,我计划在我的应用程序的管理面板中创建一个报告定义。报表定义是用于生成输出的原始SQL,然后有一个参数定义要在UI中呈现给用户,并尝试保持强类型 这些参数就是我目前遇到的问题。我可以正确地序列化参数列表,XML看起来像我期望的那样,但在某些异常情况下尝试反序列化结果 我尝试构建一个简单的方法,将XML字符串转换为对象,并得到了一些支持。我理解异常和原因,只是不知道如何解决 当我尝试反
<?xml version="1.0" encoding="utf-16"?>
<ReportParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Parameters>
<ReportParameter xsi:type="ReportParameterOfInt32">
<Name>Test</Name>
<Value xsi:type="xsd:int">4</Value>
</ReportParameter>
<ReportParameter xsi:type="ReportParameterOfDateTime">
<Name>Startdate</Name>
<Value xsi:type="xsd:dateTime">2019-04-05T22:52:25.9869948-05:00</Value>
</ReportParameter>
</Parameters>
</ReportParameters>
试验
4.
起始日期
2019-04-05T22:52:25.9869948-05:00
我认为ReportParameter上的类型是我的问题。xsi:type=“ReportParameterOfin32”
应解析为ReportParameter(或类似)
下面是我要序列化/反序列化的内容
public class ReportParameter
{
/// <summary>
/// All names are prefixed automatically with the @ sign.
/// This is the name that will appear in the query when building/writing
/// </summary>
public string Name { get; set; }
public object Value { get; set; }
}
/// <summary>
/// A generic object type that can hold many data types
/// </summary>
/// <typeparam name="T"></typeparam>
public class ReportParameter<T> : ReportParameter
{
T _value;
[XmlIgnore]
public new T Value
{
get { return _value; }
set
{
base.Value = value;
_value = value;
}
}
}
公共类报告参数
{
///
///所有名称都自动以@符号作为前缀。
///这是生成/写入时将出现在查询中的名称
///
公共字符串名称{get;set;}
公共对象值{get;set;}
}
///
///可容纳多种数据类型的通用对象类型
///
///
公共类ReportParameter:ReportParameter
{
T_值;
[XmlIgnore]
公共新T值
{
获取{返回_值;}
设置
{
基本价值=价值;
_价值=价值;
}
}
}
然后我有一个扩展方法来序列化数据(最终将写入表)
公共静态字符串序列化(此ReportParameters)
{
列表类型=新列表();
//循环所有参数
foreach(parameters.parameters中的变量a)
{
//查看此类型是否已在潜在类型列表中
if(types.Contains(a.GetType()))
{
继续;
}
//将其添加到列表中
添加(a.GetType());
}
添加(typeof(ReportParameters));
Type[]genericTypes=types.ToArray();
XmlSerializer xsSubmit=新的XmlSerializer(typeof(ReportParameters),genericTypes);
stringxml=string.Empty;
使用(var sww=new StringWriter())
{
使用(var writer=XmlWriter.Create(sww))
{
xsSubmit.Serialize(writer,参数);
xml=sww.ToString();
返回xml;
}
}
}
在编写了一个测试方法来进行简单的反序列化之后,我得到了一个可爱的异常:
消息:测试方法X.Tests.TestSerialize.SerializeGeneric引发异常:
System.InvalidOperationException:XML文档(1170)中有错误。-->System.InvalidOperationException:无法识别指定的类型:name='ReportParameterOft32',命名空间='',位于
非常感谢您提供的任何帮助。我为您提供了一个解决方案,但不幸的是,它不符合您的期望。我不知道你是否尝试过,但我希望这至少能帮助你 如果我错了,请纠正我,但似乎没有人支持您试图实现的目标,除非您推出自己的反序列化程序 可能缺少的是一种通知Xml序列化程序使用泛型类
ReportParameter
的方法,以及它应该说明哪些类型的T
因此,我没有使用泛型参数方法,而是显式地手动滚动这些类
公共类ReportParameterOft32:ReportParameter
{
int_值;
[XmlIgnore]
公共新整数值
{
获取{返回_值;}
设置
{
基本价值=价值;
_价值=价值;
}
}
}
公共类ReportParameterOfDateTime:ReportParameter
{
日期时间_值;
[XmlIgnore]
公共新日期时间值
{
获取{返回_值;}
设置
{
基本价值=价值;
_价值=价值;
}
}
}
更新了ReportParameters
(由于您的问题中没有提供,所以我猜测它的外观):
公共类报表参数
{
[XmlArrayItem(typeof(ReportParameterOft32))]
[XmlArrayItem(typeof(ReportParameterOfDateTime))]
public ReportParameter[]参数{get;set;}
}
简化序列化程序并编写反序列化程序:
私有静态字符串序列化(ReportParameters)
{
XmlSerializer xsSubmit=新的XmlSerializer(typeof(ReportParameters));
stringxml=string.Empty;
使用(var sww=new StringWriter())
{
使用(var writer=XmlWriter.Create(sww))
{
xsSubmit.Serialize(writer,参数);
xml=sww.ToString();
返回xml;
}
}
}
私有静态ReportParameters反序列化(字符串xml)
{
XmlSerializer xsSubmit=新的XmlSerializer(typeof(ReportParameters));
使用(var reader=newstringreader(xml))
{
return(ReportParameters)xsSubmit.Deserialize(reader);
}
}
编写测试代码,然后按预期执行:
var xml=序列化(
新报告参数
public static string Serialize(this ReportParameters parameters)
{
List<Type> types = new List<Type>();
// Loop over all the parameters
foreach (var a in parameters.Parameters)
{
// See if this Type is already in the list of potential types
if (types.Contains(a.GetType()))
{
continue;
}
// Add it to the List
types.Add(a.GetType());
}
types.Add(typeof(ReportParameters));
Type[] genericTypes = types.ToArray();
XmlSerializer xsSubmit = new XmlSerializer(typeof(ReportParameters), genericTypes);
string xml = string.Empty;
using (var sww = new StringWriter())
{
using (var writer = XmlWriter.Create(sww))
{
xsSubmit.Serialize(writer, parameters);
xml = sww.ToString();
return xml;
}
}
}