2013-02-20 15 views
5

Sto usando NHibernate per i miei C# pojects e quindi ho diverse classi del modello.alternativa a chiamare un metodo virtuale in C#

lascia supporre il seguente esempio:

using System; 

namespace TestProject.Model 
{ 
    public class Room 
    { 
     public virtual int Id { get; set; } 
     public virtual string UniqueID { get; set; } 
     public virtual int RoomID { get; set; } 
     public virtual float Area { get; set; } 

    } 
} 

Mappatura questi oggetti con NHibernate funziona bene finora. Ora voglio generare un nuovo oggetto Room e voglio memorizzarlo nel database. Per evitare di impostare separatamente ciascun membro, aggiungo un nuovo costruttore alla classe del modello. Di seguito i membri virtuali scrivo:

public RoomProperty() 
{ 

} 


public RoomProperty(int pRoomId, int pArea) 
{ 
     UniqueID = Guid.NewGuid().ToString(); 
     RoomID = pRoomId; 
     Area = pArea; 
} 

Analizzando il mio codice con FxCop mi dice il seguente:

"ConstructorShouldNotCallVirtualMethodsRule" 
This rule warns the developer if any virtual methods are called in the constructor of a non-sealed type. The problem is that if a derived class overrides the method then that method will be called before the derived constructor has had a chance to run. This makes the code quite fragile. 

This page descrive anche il motivo per cui questo è sbagliato e ho anche capirlo. Ma io non sono sicuro come risolvere il problema.

Quando sono a cancellare tutti i costruttori e aggiungi il metodo seguente ...

public void SetRoomPropertyData(int pRoomId, int pArea) 
     { 
      UniqueID = Guid.NewGuid().ToString(); 
      RoomID = pRoomId; 
      Area = pArea; 

     } 

.... per impostare i dati dopo ho chiamato il costruttore di serie non posso iniziare il mio aplication becaue NHibernate fallisce l'inizializzazione. Dice:

NHibernate.InvalidProxyTypeException: The following types may not be used as proxies: 
VITRIcadHelper.Model.RoomProperty: method SetRoomPropertyData should be 'public/protected virtual' or 'protected internal virtual' 

Ma l'impostazione di questo metodo per virtual sarebbe lo stesso errore quando ho appena impostato i membri virtuali nel costruttore. Come posso evitare questi errori (violazioni)?

+0

perché non impostare valori nei campi non proprietà in costruzione? –

+0

@voroninp non è possibile accedere ai campi in modo semplice con NHibernate – Andrey

+0

Perché il mio modello ha in realtà circa 10 membri e io creo nuovi oggetti della stanza qiet iften. Non voglio impostare separatamente ogni proprietà. – Metalhead89

risposta

4

Il problema sta nel set virtuale. Passando un valore alla proprietà virtuale nel costruttore della classe base verrà utilizzato il set overriden invece il set base. Se l'override impostato si basa sui dati nella classe derivata, allora si è nei guai, perché il costruttore della classe derivata non era ancora stato creato.

Se siete assolutamente sicuri, che ogni sottoclasse non utilizzerà i dati del suo Stato nel set sovresposta, allora è possibile inizializzare le proprietà virtuali a costruttore della classe base. Prendi in considerazione l'aggiunta di un avviso appropriato alla documentazione.

Se possibile, cercate di creare campi backing per ogni proprietà e utilizzarli in classe di base contructor.

Si può anche rimandare proprietà di inizializzazione per la classe derivata. Per ottenere ciò, creare un metodo di inizializzazione nella classe base che si invoca nel costruttore della classe derivata.

1

mi aspetto una delle seguenti al lavoro:

  1. Fai le proprietà non virtuale (preferito a patto che NHibernate lo supporta).
  2. Variazione dalle proprietà di auto-implementato per gli oggetti con un campo di supporto esplicito, e impostare i campi nel costruttore invece di impostare le proprietà.
  3. Creare un Create metodo statico che costruisce l'oggetto prima, e poi imposta valori alle proprietà prima di restituire l'oggetto costruito.

Edit: Dal commento vedo l'opzione # 3 non era chiaro.

public class Room 
{ 
    public virtual int Id { get; set; } 
    public virtual string UniqueID { get; set; } 
    public virtual int RoomID { get; set; } 
    public virtual float Area { get; set; } 

    public static Room Create(int roomId, int area) 
    { 
     Room room = new Room(); 
     room.UniqueID = Guid.NewGuid().ToString(); 
     room.RoomID = roomId; 
     room.Area = area; 
     return room; 
    } 
} 
+0

NHibernate non supporta proprietà non virtuali. E inoltre non posso impostare il metodo di creazione statico perché poi anche le proprietà devono essere statiche che non è quello che voglio (non sono anch'io sicuro se funzionasse) – Metalhead89

+0

Ho modificato il mio post per chiarire l'opzione 3. Il 'Create' il metodo è statico, ma le proprietà no. –

+0

L'opzione 3 ha più senso se si rende protetto il costruttore, quindi l'unico modo per costruire un'istanza di 'Room' è con il metodo statico. –

Problemi correlati