2010-09-15 18 views
3

Considérez ce qui suit. Vous avez une classe que vous voulez sérialiser avec XmlSerializer qui a une méthode générique du public avec une contrainte de type où le type est dans un autre assemblage:XmlSerializer requiert XmlInclude pour la méthode publique avec contrainte générique si type dans un autre assembly ET nécessite que ce type soit serialiable!

using BarStuff; 

namespace FooStuff { 
    public class Foo { 
    ... 
    public T GetBar<TBar, T>(string key) where TBar : Bar<T> { 
     ... 
    } 
    } 
} 

Vous ne penseriez pas XmlSerializer même à se préoccuper des méthodes et généralement pas. Ce qui suit à la fois beau travail:

//private, serializer doesn't care about it 
private T GetBar<TBar, T>(string key) where TBar : Bar<T> { 
    ... 
} 

//no generic type constraint, serializer also doesn't care about it 
public Bar GetBar(string key) { 
    ... 
} 

En outre, si la barre de type est dans le même ensemble que Foo alors le sérialiseur sera aussi parfaitement heureux. Lorsque vous exécutez le premier exemple, si Bar est défini dans un assembly séparé, vous obtenez une exception d'exécution indiquant que vous devez ajouter une référence à l'assembly contenant Bar, même si vous avez déjà cet assembly dans votre projet références. Vous pouvez contourner ce problème en utilisant XmlInclude:

[XmlInclude(typeof(Bar))] 
public class Foo { 
    public T GetBar<TBar, T>(string key) where TBar : Bar<T> { 
    ... 
    } 
} 

Cependant si la barre est pas sérialisable, et il n'y a aucune raison pour laquelle il devrait être, vous aurez maintenant une exception d'exécution de la première fois qu'il touche quelque chose, il ne peut pas sérialiser, comme une propriété publique qui renvoie une interface en tant que type, une classe sans constructeur sans paramètre, etc.!

connexes, mais pas aussi détaillé: XmlSerializer is throwing InvalidOperationException when using the generic type constraint where

aussi: Microsoft's take on the problem

+0

voulez-vous essayer cette réponse de l'autre question que vous avez mentionné? - http://stackoverflow.com/questions/2361563/xmlserializer-is-throwing-invalidoperationexception-when-using-the-generic-type-c/2381606#2381606 –

+0

J'ai vu ça :) Mais comme mentionné ci-dessus, quand vous [ XmlInclude (typeof (Bar))] XmlSerializer échouera si Bar n'est pas sérialisable, même s'il n'est jamais sérialisé, et il n'y a aucune raison que Bar devrait être sérialisable. – nrkn

Répondre

2

Quelques solutions de contournement:

  • Utilisez un sérialiseur différent tel que DataContractSerializer
  • Assurez-vous que les types sont dans le même ensemble de sorte que le XmlInclude est inutile (beurk)
  • Changer de barre pour le rendre sérialisable (beurk)
  • Évitez d'avoir des méthodes de ce genre, ie que par sérialisation objets de type DTO et ayant une telle fonctionnalité ailleurs
  • Ceci est sournoise et hackish ... comprennent une classe factice qui est sérialisable dans le même assemblage que votre barre de type, puis XmlInclude qu'au lieu, cela va rendre le sérialiseur heureux, à savoir:

Exemple:

namespace BarStuff { 
    //the serializer is perfectly happy with me 
    public class DummyBar{} 

    //the serializer doesn't like me 
    public class Bar{ 
    ... 
    } 

    ... 
} 

using BarStuff; 
namespace FooStuff { 
    [XmlInclude(typeof(DummyBar))] 
    public class Foo { 
    public T GetBar<TBar, T>(string key) where TBar : Bar<T> { 
     ... 
    } 
    }