2009-09-06 4 views
0

Je crée une file d'attente de messages dans une base de données. Chaque élément en file d'attente stocke un ID et quelques autres choses. Mais le champ clé est IncomingMessage. Dans la base de données, je stocke une version sérialisée de IncomingMessage car il peut s'agir d'un certain nombre de types (comme NewWorkorderMessage ou EmployeeStatusChangeMessage). Donc le champ dans ma classe QueuedMessage _incomingMessage est une chaîne. Cependant, je voudrais éviter la chaîne virtuelle publique habituelle QueuedMessage {get; set;} business et avoir simplement un objet public GetMessage() et une méthode publique SetMessage (message d'objet) pour gérer la sérialisation automatique du .NET classer dans le XML. Naturellement, l'application appelante veut traiter des instances de classes Message, pas de XML qu'elle doit sérialiser/désérialiser. Utilisation de FluentNHibernate Je ne suis pas sûr de savoir comment faire cela. J'ai essayé quelques approches différentes telles que la suivante, mais cela nécessite encore que je possède la propriété.Stockage d'un champ dans FluentNHibernate en utilisant un type, mais en accédant par des méthodes comme un autre type

Des idées? Merci.

  Map(x => x.IncomingMessage) 
      .Not.Nullable() 
      .WithLengthOf(3000) 
      .Access.AsReadOnlyPropertyThroughCamelCaseField(Prefix.Underscore); 

Répondre

0

Eh bien, j'ai fait quelque chose de similaire avec Images. Je stocke les images sous forme de blobs dans la BD, mais je veux y accéder en tant que classes Image sur mes classes POCO. Je l'ai fait en utilisant l'interface IPropertyAccessor.

Mon Fluent NHibernate ressemble à ce

 Map(entity => entity.Image) 
      .Access.Using<ImagePropertyAccessor>() 
      .Nullable(); 

et mon IPropertyAccessor ressemble à ceci:

public class ImagePropertyAccessor : IPropertyAccessor 
{ 
    #region Setter 

    private class ImageGetterSetter : IGetter, ISetter { 
     PropertyInfo _property; 
     ImageFormat _imageFormat; 
     public ImageGetterSetter(PropertyInfo property, ImageFormat imageFormat) 
     { 
      if (property == null) throw new ArgumentNullException("property"); 
      if (property.PropertyType != typeof(Image)) throw new ArgumentException("property"); 
      _property = property; 
      _imageFormat = imageFormat; 
     } 

     public void Set(object target, object value) { 
      var image = Deserialise((byte[]) value); 
      _property.SetValue(target, image, null); 
     } 

     public object Get(object target) 
     { 
      var image = (Image)_property.GetValue(target, null); 
      var data = Serialise(image); 
      return data; 
     } 

     private byte[] Serialise(Image image) 
     { 
      if (image == null) 
       return null; 
      var ms = new MemoryStream(); 
      image.Save(ms, _imageFormat); 
      return ms.ToArray(); 
     } 

     private Image Deserialise(byte[] data) 
     { 
      if (data == null || data.Length == 0) 
       return null; 
      var ms = new MemoryStream(data); 
      return Image.FromStream(ms); 
     } 

     public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) 
     { 
      return Get(owner); 
     } 

     public Type ReturnType 
     { 
      get { return typeof (byte[]); } 
     } 

     public string PropertyName { 
      get { return _property.Name; } 
     } 

     public MethodInfo Method { 
      get { return null; } 
     } 
    } 

    #endregion 

    public IGetter GetGetter(Type theClass, string propertyName) { 
     return new ImageGetterSetter(theClass.GetProperty(propertyName), ImageFormat.Bmp); 
    } 

    public ISetter GetSetter(Type theClass, string propertyName) { 
     return new ImageGetterSetter(theClass.GetProperty(propertyName), ImageFormat.Bmp); 
    } 

    public bool CanAccessThroughReflectionOptimizer { 
     get { return false; } 
    } 
} 

Ce que je ne sais pas, ou plutôt ne l'ai pas étudié, est l'effet de pousser la sérialisation/désérialisation en NHibernate. Évidemment, il y a un surcoût supplémentaire associé à cela. Dans mon exemple, ce n'est pas trop mal, car je n'ai pas affaire à des masses d'entités et de données. Pour des raisons de performances, mieux vaut utiliser une chaîne désérialisée et exposer vos propres méthodes pour la convertir. Mais l'IPropertyAccessor est bon pour préserver la conception de vos classes POCO.

Questions connexes