开发者

How to dynamically provide T .. class ObjectXMLSerializer<T> where T : class

开发者 https://www.devze.com 2023-01-16 16:00 出处:网络
Ok so the class I want to use is declared with: public static class ObjectXMLSerializer<T> where T : class

Ok so the class I want to use is declared with:

public static class ObjectXMLSerializer<T> where T : class

I have many objects that I want to serialize, but I do not know their "class"

object myclass = new MyNamespace.MyClass() as object;

How do 开发者_JAVA百科I do the following... ?

ObjectXMLSerializer< ? >.Save(myclass,"output.xml");

I can't do this because the type that is expected, is "class"

ObjectXMLSerializer< myclass.GetType() >.Save(myclass,"output.xml");

And this just wouldnt work ...

ObjectXMLSerializer< object >.Save(myclass,"output.xml");

Any thoughts would be appreciated!


You're trying to use generics for something it isn't designed for.

Generics are meant to give compile-time safety (and express information about the API at compile-time). You don't know the types involved at compile-time, so you've got a problem.

Options:

  • Use a non-generic API
  • Call the generic API via reflection
  • Redesign your code so that the relevant method does know the type at compile-time (e.g. make the method that calls Save generic too)


You could try this without generics:

public static class ObjectXMLSerializer
{
    public static void Save(IXmlSerializable myObject, string fileName) 
    {
        // whatever
    }
}

Although, depending on what you're trying to do, you might be better off just using the framework's XmlSerializer instead of writing your own.


Don't use generics if XML serialization is all that you care about:

public static class ObjectXMLSerializer { 
  public static void Save(object objectToSerialize, string fileName) { 
    // ...
  } 
} 

Alternatively, look at the XmlSerializer class, it might already cover your requirements:

public static class ObjectXMLSerializer {
  public static void Save(object objectToSerialize, string fileName) {
    var serializer = new XmlSerializer(objectToSerialize.GetType());
    using (var stream = File.OpenWrite(fileName)) {
      serializer.Serialize(stream, objectToSerialize);
    }
  }
}

To deserialize, though, since you must know the compile-time type of the object that you want, you could use generics on the deserialization method:

public static class ObjectXMLDeserializer {
  public static T Load<T>(string fileName) { 
    var serializer = new XmlSerializer(typeof(T));
    using (var stream = File.OpenRead(fileName)) {
      return (T)serializer.Deserialize(stream);
    }
  } 
}


I'm recommending an interface IXmlSerializable with the method Serialize() exposed. If you need to refer to them generically (without knowing it's ClassA or ClassB , you can cast or box them to the interface and call the method.

Usually, I just attribute my objects with Serializable and make sure all the properties are serializable or attribute the property with XmlIgnore / Nonserialized

[Serializable]
public class MyClass
{
     [Nonserialized]
     private DataTable _myProperty;
     [XmlIgnore]
     public DataTable MyProperty { get; set; }
}


Despite the fact that you might be doing it wrong, you can construct a generic type and an instance of generic type using reflection. For example, if I would like to create a List<int> I can write

Type t = typeof(List<>).MakeGenericType(typeof(int));
object list = Activator.CreateInstance(t);
// add an integer to list and get Count property        
t.GetMethod("Add").Invoke(list, new object[] {3});
int count = (int) t.GetProperty("Count").GetValue(list, null);

... and that is why everybody would suggest redesigning your class.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号