2013-02-20 46 views
5

में वर्चुअल विधि को कॉल करने के लिए वैकल्पिक मैं अपने सी # pojects के लिए NHibernate का उपयोग कर रहा हूं और इसलिए मेरे पास कई मॉडल वर्ग हैं।सी #

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

    } 
} 

इन वस्तुओं का मिलान के साथ NHibernate अब तक ठीक काम करता है:

निम्न उदाहरण मान देता है। अब मैं एक नया कक्ष वस्तु उत्पन्न करना चाहता हूं और मैं इसे डेटाबेस में संग्रहीत करना चाहता हूं। प्रत्येक सदस्य को अलग-अलग सेट करने से बचने के लिए, मैं मॉडल वर्ग में एक नया कन्स्ट्रक्टर जोड़ता हूं। आभासी सदस्यों नीचे मैं लिखने:

public RoomProperty() 
{ 

} 


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

FxCop के साथ अपने कोड का विश्लेषण करना मेरा पीछा बताता है:

"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 भी बताता है कि क्यों यह गलत है और मैं भी यह समझते हैं। लेकिन मैं इस समस्या को हल करने के लिए शर्मिंदा नहीं हूं।

जब मैं सभी निर्माताओं को मिटाने और निम्न विधि जोड़ें ...

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

     } 

.... के बाद मैं मानक निर्माता कहा जाता है मैं नहीं कर सकते मेरे आवेदन शुरू becaue NHibernate आरंभ में विफल रहता है डेटा सेट करने। इसे कहते हैं:

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' 

लेकिन आभासी के लिए इस विधि की स्थापना जब मैं सिर्फ निर्माता में आभासी सदस्यों सेट के रूप में ही गलती होगी। मैं इन गलतियों (उल्लंघन) से कैसे बच सकता हूं?

+0

क्यों खेतों में मूल्य निर्धारित नहीं करना निर्माण पर गुण नहीं है? –

+0

@ voroninp आप उन क्षेत्रों तक नहीं पहुंच सकते हैं जो आसानी से NHibernate – Andrey

+0

के साथ हैं क्योंकि मेरे मॉडल में वास्तव में लगभग 10 सदस्य हैं और मैं नए कमरे की वस्तुओं qiet iften बनाते हैं। मैं प्रत्येक संपत्ति को अलग से सेट नहीं करना चाहता हूं। – Metalhead89

उत्तर

4

समस्या आभासी सेट में निहित है। बेस क्लास कन्स्ट्रक्टर में वर्चुअल प्रॉपर्टी के लिए मान पास करने से बेस सेट के बजाय ओवर्रिडन सेट का उपयोग किया जाएगा। यदि अतिरंजित सेट व्युत्पन्न वर्ग में डेटा पर निर्भर करता है, तो आप परेशानी में हैं, क्योंकि व्युत्पन्न वर्ग का निर्माता अभी तक नहीं किया गया है।

यदि आप पूरी तरह से सुनिश्चित हैं कि कोई सबक्लस अतिरंजित सेट में अपने राज्य के किसी भी डेटा का उपयोग नहीं करेगा, तो आप बेस क्लास कन्स्ट्रक्टर में आभासी गुणों को प्रारंभ कर सकते हैं। दस्तावेज़ीकरण के लिए एक उचित चेतावनी जोड़ने पर विचार करें।

यदि संभव हो, तो प्रत्येक संपत्ति के लिए बैकिंग फ़ील्ड बनाने का प्रयास करें और बेस क्लास कन्स्ट्रक्टर में उनका उपयोग करें।

आप व्युत्पन्न कक्षा में गुण प्रारंभिक स्थगित भी कर सकते हैं। इसे प्राप्त करने के लिए, बेस क्लास में प्रारंभिक विधि बनाएं जिसे आपने व्युत्पन्न कक्षा के निर्माता में बुलाया है।

1

मैं काम करने के लिए निम्न में से एक की उम्मीद:

  1. गुण गैर आभासी (जब तक NHibernate इसका समर्थन करता है जो कि अनुशंसित) बनाओ।
  2. स्वत: कार्यान्वित गुणों से एक स्पष्ट बैकिंग फ़ील्ड वाले गुणों में बदलें, और गुणों को सेट करने के बजाय फ़ील्ड को कन्स्ट्रक्टर में सेट करें।
  3. एक स्थिर Create विधि बनाएं जो ऑब्जेक्ट को पहले बनाता है, और उसके बाद निर्मित ऑब्जेक्ट को वापस करने से पहले गुणों को मान सेट करता है।

संपादित करें: टिप्पणी से मुझे विकल्प # 3 स्पष्ट नहीं था।

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 गैर वर्चुअल गुणों का समर्थन नहीं करता है। और मैं भी निर्माण विधि स्थैतिक सेट नहीं कर सकता क्योंकि तब भी गुण स्थिर होना चाहिए जो मैं नहीं चाहता हूं (अगर यह काम करेगा तो मैं भी शर्मिंदा नहीं हूं) – Metalhead89

+0

मैंने विकल्प पोस्ट को स्पष्ट करने के लिए अपनी पोस्ट संपादित की है। 'बनाएं' विधि स्थिर है, लेकिन गुण नहीं हैं। –

+0

विकल्प 3 अधिक समझ में आता है यदि आप कन्स्ट्रक्टर को सुरक्षित करते हैं, इसलिए 'कक्ष' का उदाहरण बनाने का एकमात्र तरीका स्थैतिक विधि के साथ है। –