2010-09-16 3 views
0

Ok поэтому класс я хочу использовать декларируется с:Как динамически обеспечить T .. класс ObjectXMLSerializer <T> где T: класс

public static class ObjectXMLSerializer<T> where T : class 

У меня есть много объектов, которые я хочу сериализации, но я не знают свой «класс»

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

Как это сделать ...?

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

Я не могу этого сделать, потому что тот тип, который, как ожидается, является "класс"

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

И это просто не работал бы ...

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

Любые мысли были бы оценили!

+1

«И это просто не сработает ...» - каким образом? –

+0

Этот метод не работает по назначению, потому что объект не отражает структуру исходного объекта. – Chris

+0

Это не очень описательно. То, что показывает желаемый результат и фактический результат, будет более полезным. Пожалуйста, прочитайте http://tinyurl.com/so-hints –

ответ

0

Не использовать дженерики, если XML сериализации все, что вы заботитесь о :

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

с другой стороны, посмотрите на XmlSerializer класс, он уже может покрыть ваши требования:

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); 
    } 
    } 
} 

десериализации, хотя, так как вы обязательно знать тип во время компиляции объекта, который вы хотите, вы могли бы использовать дженерики по методу десериализации:

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); 
    } 
    } 
} 
+0

Эти две функции делают довольно приличные методы расширения. – asawyer

+0

@asawyer: совершенно! Взгляните на [этот пост] (http://codecrafter.blogspot.com/2010/02/c-quasi-mixins-pattern.html) за другой подход к этой теме. –

+0

Это было интересно читать, спасибо. – asawyer

7

Вы пытаетесь использовать дженерики для чего-то, для чего он не предназначен.

Общие сведения предназначены для предоставления времени компиляции безопасности (и выражения информации об API при компиляции). Вы не знаете типы, участвующие во время компиляции, поэтому у вас есть проблема.

Варианты:

  • использовать не универсальный API
  • Вызов родовое API с помощью отражения
  • Редизайн код так, чтобы соответствующий метод делает знать тип во время компиляции (например, сделать метод, который вызывает Save родовое тоже)
+2

Я прошу добавить новую функцию на SO. Продвинутая кнопка «вверх». Тот, который подразумевает «Проклятия! Я трясу кулаком у тебя, Джон Скит!» - Все в хорошем весе. – Josh

+0

Спасибо, Джон, особенно за такой быстрый и точный ответ! – Chris

1

Вы можете попробовать т его без дженерики:

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

Хотя, в зависимости от того, что вы пытаетесь сделать, вы могли бы быть лучше только с помощью фреймворка XmlSerializer вместо того, чтобы писать свои собственные.

+0

Объекту не нужно реализовывать IXmlSerializable для сериализации в XML ... этот интерфейс используется только для предоставления пользовательской сериализации XML –

+0

@Thomas: Абсолютно. Но я решил, что это будет простой способ сузить область объектов, которые могут быть переданы этому методу. Вероятно, лучше всего заменить его специальным интерфейсом, если OP пойдет по этому маршруту. –

0

Я рекомендую интерфейс IXmlSerializable с методом Serialize() выставлен. Если вам нужно обратиться к ним в общем случае (не зная, что это ClassA или ClassB, вы можете отобразить или поместить их в интерфейс и вызвать метод.

Обычно я просто приписывать свои объекты с Serializable и убедитесь, что все свойства сериализуемы или приписывать свойство с XmlIgnore/Nonserialized

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

Несмотря на то, что вы могли бы делайте это неправильно, вы можете создать общий тип и экземпляр родового типа с использованием отражения. Например, если я хотел бы создать List<int> я могу написать

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); 

... и именно поэтому каждый хотел бы предложить перепроектирование своего класса.

+0

это какой-то болезненный код ... – Chris

Смежные вопросы