C# 反序列化GenericObject列表<;T>;形形色色

C# 反序列化GenericObject列表<;T>;形形色色,c#,xml,xml-serialization,C#,Xml,Xml Serialization,我的最终目标是存储一些用于生成用于报告的SQL的参数,以减少(或删除?)SQL注入的可能性 因此,在我的解决方案中,我计划在我的应用程序的管理面板中创建一个报告定义。报表定义是用于生成输出的原始SQL,然后有一个参数定义要在UI中呈现给用户,并尝试保持强类型 这些参数就是我目前遇到的问题。我可以正确地序列化参数列表,XML看起来像我期望的那样,但在某些异常情况下尝试反序列化结果 我尝试构建一个简单的方法,将XML字符串转换为对象,并得到了一些支持。我理解异常和原因,只是不知道如何解决 当我尝试反

我的最终目标是存储一些用于生成用于报告的SQL的参数,以减少(或删除?)SQL注入的可能性

因此,在我的解决方案中,我计划在我的应用程序的管理面板中创建一个报告定义。报表定义是用于生成输出的原始SQL,然后有一个参数定义要在UI中呈现给用户,并尝试保持强类型

这些参数就是我目前遇到的问题。我可以正确地序列化参数列表,XML看起来像我期望的那样,但在某些异常情况下尝试反序列化结果

我尝试构建一个简单的方法,将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;
                }
            }
        }