Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 泛型和XmlSerializer的继承转换问题_C#_Generics_Xml Serialization_Casting - Fatal编程技术网

C# 泛型和XmlSerializer的继承转换问题

C# 泛型和XmlSerializer的继承转换问题,c#,generics,xml-serialization,casting,C#,Generics,Xml Serialization,Casting,如何强制转换对象的实例并使其成为该类型的对象 我有一个类myClass1,它是myClass2和myClass3的基类。我想用myClass1进行审计,因为我只想审计myClass1中的数据。因为myClass2和myClass3继承自myClass1,所以可以将myClass1的实例设置为myClass2的实例示例: myClass2 foo = new myClass2(); foo.prop1 = "some data"; foo.prop2 = "some More Data"; my

如何强制转换对象的实例并使其成为该类型的对象

我有一个类myClass1,它是myClass2和myClass3的基类。我想用myClass1进行审计,因为我只想审计myClass1中的数据。因为myClass2和myClass3继承自myClass1,所以可以将myClass1的实例设置为myClass2的实例示例:

myClass2 foo = new myClass2();
foo.prop1 = "some data";
foo.prop2 = "some More Data";

myClass1 bar = foo;
问题的出现是因为我使用的是泛型

 public static IXPathNavigable SerializeGeneric<T>(T serializableObject)
    {
        String XmlizedString = "Error processing request";
        XmlDocument XMLObject = new XmlDocument();
        try
        {
            MemoryStream memoryStream = new MemoryStream();
            XmlSerializer xs = new XmlSerializer(serializableObject.GetType());
name的值是“myClass2”,这很有意义,因为内存中的数据实际上是一个myClass2,而条下面只是一个指向myClass2对象的指针。无需创建新实例并将该新实例的值设置为该对象,如

myClass1 bar = new myClass1(){prop1=foo.prop1, prop2=foo.prop2};

我真的不想这样做。

不知道这是否可行,但请尝试将其更改为:

XmlSerializer xs = new XmlSerializer(typeof(T));
这将告诉序列化程序创建您指定的任何类型的序列化程序实例。虽然我不确定序列化程序是否会这样做

编辑:只要你打电话

SerializeGeneric<MyClass1>(foo);
SerializeGeneric(foo);
再次编辑:

就用这个试过了:

    public void Test()
    {
        var obj = new Foo2() { Prop1 = "Test", Prop2 = "Test2" };

        SerializeGeneric((Foo1)obj);
    }

    private void SerializeGeneric<T>(T obj)
    {
        StringWriter writer = new StringWriter();    
        XmlSerializer xs = new XmlSerializer(typeof(T));
        xs.Serialize(writer, obj);

        Console.WriteLine(writer.ToString());
    }


    public class Foo1
    {
        public string Prop1 { get; set; }
    }

    public class Foo2 : Foo1
    {
        public string Prop2 { get; set; }
    }
公共无效测试()
{
var obj=newfoo2(){Prop1=“Test”,Prop2=“Test2”};
序列化通用((Foo1)obj);
}
私有对象(T obj)
{
StringWriter编写器=新的StringWriter();
XmlSerializer xs=新的XmlSerializer(typeof(T));
序列化(writer,obj);
Console.WriteLine(writer.ToString());
}
公开课1
{
公共字符串Prop1{get;set;}
}
公共类Foo2:Foo1
{
公共字符串Prop2{get;set;}
}
它抛出一个“意外类型”的异常。事实证明,序列化程序不会将对象序列化为其他类型。我不确定有什么办法能让它做到

我想您可以编写一个自定义序列化程序,或者编写一个简单的反射方法来执行memberwiseclone-ish操作,该操作只复制您想要的foo1中的属性

有趣的是,如果将[xmlclude(typeof(Foo2))]添加到Foo1声明中,则不会出现错误,尽管它会输出以下胡言乱语:

<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="Foo2">
  <Prop1>Test</Prop1>
  <Prop2>Test2</Prop2>
</Foo1>

试验
测试2
这是一个Foo1声明,具有Foo1和Foo2属性,类型声明为Foo2。。。有趣

最后一个:

这很管用,不过我不确定我会推荐它

    public void Test ()
    {
        var obj = new Foo2() { Prop1 = "Test", Prop2 = "Test2" };

        SerializeGeneric(ShallowCopy<Foo1>(obj));
    }

    private T ShallowCopy<T>(object input)
        where T : class, new()
    {
        T newObj = Activator.CreateInstance<T>();
        Type oldType = input.GetType();
        BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.SetField;
        var oldProperties = oldType.GetProperties(flags);

        foreach (var pd in typeof(T).GetProperties(flags))
        {
            var oldPd = oldProperties.FirstOrDefault(x=>x.Name == pd.Name && x.PropertyType == pd.PropertyType);

            if(oldPd != null)
               pd.SetValue(newObj, oldPd.GetValue(input, null), null);
        }

        return newObj;
    }
公共无效测试()
{
var obj=newfoo2(){Prop1=“Test”,Prop2=“Test2”};
一般(浅镜(obj));
}
私有T浅拷贝(对象输入)
其中T:class,new()
{
T newObj=Activator.CreateInstance();
Type oldType=input.GetType();
BindingFlags flags=BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.SetField;
var oldProperties=oldType.GetProperties(标志);
foreach(typeof(T).GetProperties(flags)中的varpd)
{
var oldPd=oldProperties.FirstOrDefault(x=>x.Name==pd.Name&&x.PropertyType==pd.PropertyType);
如果(oldPd!=null)
pd.SetValue(newObj,oldp.GetValue(输入,null),null);
}
返回newObj;
}
这将为您提供:

<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Prop1>Test</Prop1>
</Foo1>

试验

看起来很完美。

不知道这是否有效,但请尝试将其更改为:

XmlSerializer xs = new XmlSerializer(typeof(T));
这将告诉序列化程序创建您指定的任何类型的序列化程序实例。虽然我不确定序列化程序是否会这样做

编辑:只要你打电话

SerializeGeneric<MyClass1>(foo);
SerializeGeneric(foo);
再次编辑:

就用这个试过了:

    public void Test()
    {
        var obj = new Foo2() { Prop1 = "Test", Prop2 = "Test2" };

        SerializeGeneric((Foo1)obj);
    }

    private void SerializeGeneric<T>(T obj)
    {
        StringWriter writer = new StringWriter();    
        XmlSerializer xs = new XmlSerializer(typeof(T));
        xs.Serialize(writer, obj);

        Console.WriteLine(writer.ToString());
    }


    public class Foo1
    {
        public string Prop1 { get; set; }
    }

    public class Foo2 : Foo1
    {
        public string Prop2 { get; set; }
    }
公共无效测试()
{
var obj=newfoo2(){Prop1=“Test”,Prop2=“Test2”};
序列化通用((Foo1)obj);
}
私有对象(T obj)
{
StringWriter编写器=新的StringWriter();
XmlSerializer xs=新的XmlSerializer(typeof(T));
序列化(writer,obj);
Console.WriteLine(writer.ToString());
}
公开课1
{
公共字符串Prop1{get;set;}
}
公共类Foo2:Foo1
{
公共字符串Prop2{get;set;}
}
它抛出一个“意外类型”的异常。事实证明,序列化程序不会将对象序列化为其他类型。我不确定有什么办法能让它做到

我想您可以编写一个自定义序列化程序,或者编写一个简单的反射方法来执行memberwiseclone-ish操作,该操作只复制您想要的foo1中的属性

有趣的是,如果将[xmlclude(typeof(Foo2))]添加到Foo1声明中,则不会出现错误,尽管它会输出以下胡言乱语:

<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="Foo2">
  <Prop1>Test</Prop1>
  <Prop2>Test2</Prop2>
</Foo1>

试验
测试2
这是一个Foo1声明,具有Foo1和Foo2属性,类型声明为Foo2。。。有趣

最后一个:

这很管用,不过我不确定我会推荐它

    public void Test ()
    {
        var obj = new Foo2() { Prop1 = "Test", Prop2 = "Test2" };

        SerializeGeneric(ShallowCopy<Foo1>(obj));
    }

    private T ShallowCopy<T>(object input)
        where T : class, new()
    {
        T newObj = Activator.CreateInstance<T>();
        Type oldType = input.GetType();
        BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.SetField;
        var oldProperties = oldType.GetProperties(flags);

        foreach (var pd in typeof(T).GetProperties(flags))
        {
            var oldPd = oldProperties.FirstOrDefault(x=>x.Name == pd.Name && x.PropertyType == pd.PropertyType);

            if(oldPd != null)
               pd.SetValue(newObj, oldPd.GetValue(input, null), null);
        }

        return newObj;
    }
公共无效测试()
{
var obj=newfoo2(){Prop1=“Test”,Prop2=“Test2”};
一般(浅镜(obj));
}
私有T浅拷贝(对象输入)
其中T:class,new()
{
T newObj=Activator.CreateInstance();
Type oldType=input.GetType();
BindingFlags flags=BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.SetField;
var oldProperties=oldType.GetProperties(标志);
foreach(typeof(T).GetProperties(flags)中的varpd)
{
var oldPd=oldProperties.FirstOrDefault(x=>x.Name==pd.Name&&x.PropertyType==pd.PropertyType);
如果(oldPd!=null)
pd.SetValue(newObj,oldp.GetValue(输入,null),null);
}
返回newObj;
}
这将为您提供:

<Foo1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Prop1>Test</Prop1>
</Foo1>

试验

这看起来很完美。

要在继承时正确执行xml序列化,有两条准则:

  • 始终使用
    typeof(Base)
    (序列化或反序列化时)创建
    XmlSerializer