2013-04-29 2 views
1

je dois ajouter le System.Drawing.Color au modèle par défaut, mais ses valeurs sont en lecture seule, donc j'essayé de faire ce qui suit:InvalidOperationException lorsque SetFactory pour RuntimeTypeModel

MetaType colorMeta = RuntimeTypeModel.Default.Add(typeof(Color), true); 

MethodInfo methodInfo = typeof(Color).GetMethod("FromArgb", new Type[] { typeof(Int32), typeof(Int32), typeof(Int32), typeof(Int32) }); 

colorMeta.AddField(1, "A"); 
colorMeta.AddField(2, "R"); 
colorMeta.AddField(3, "G"); 
colorMeta.AddField(4, "B"); 

colorMeta.SetFactory(methodInfo); 

et je reçois:

InvalidOperationException : Operation is not valid due to the current state of the object 

Répondre

1

Il y a quelques problèmes là-bas; Premièrement, une "usine" dans ce contexte devrait être une méthode statique qui crée des instances du type, mais pas faire cela avec les valeurs - il n'est pas destiné à être utilisé avec des méthodes comme FromArgb.

En second lieu, protobuf-net ne sera pas en mesure de faire beaucoup avec les A/R/G/B propriétés car ils manquent setters. Votre pensée a du mérite, cependant - c'est très similaire à la fonctionnalité de tuple automatique existante - la principale différence étant que le code de tuple automatique veut qu'il y ait un constructeur qui corresponde à tous les membres évidents. Color n'a pas un tel constructeur, mais il vaut peut-être mieux que je cherche à voir s'il est possible d'étendre le code de tuple pour permettre les méthodes d'usine au lieu du constructeur.

Cependant, pour l'instant (sans changer de code), il y a probablement deux options viables:

  • dire le modèle de sérialisation les privés champs et de sauter le constructeur
  • utiliser un
  • de substitution

Je suggérerais probablement que ce dernier est plus facile. Par exemple, les travaux suivants (en utilisant la disposition fixe de 4 octets car cela devrait bien fonctionner pour toutes les couleurs):

using ProtoBuf; 
using ProtoBuf.Meta; 
using System.Drawing; 

[ProtoContract] 
struct ColorSurrogate 
{ 
    public int Value { get { return value; } } 
    [ProtoMember(1, DataFormat = DataFormat.FixedSize)] 
    private int value; 
    public ColorSurrogate(int value) { this.value = value; } 

    public static explicit operator Color(ColorSurrogate value) { 
     return Color.FromArgb(value.Value); 
    } 
    public static explicit operator ColorSurrogate(Color value) { 
     return new ColorSurrogate(value.ToArgb()); 
    } 
} 
[ProtoContract] 
class Foo { 
    [ProtoMember(1)] 
    public Color Color { get; set; } 
} 

class Program { 
    static void Main() { 
     RuntimeTypeModel.Default.Add(typeof(Color), false) 
      .SetSurrogate(typeof(ColorSurrogate)); 

     var foo = new Foo { Color = Color.Firebrick }; 
     var clone = Serializer.DeepClone(foo); 
    } 
} 
Questions connexes