2009-07-30 17 views
7

यह देखते हुए कि काफी स्थिर डेटा नहीं किया जा पुनः आकलन लेकिन इसके बजाय कैश की गई चाहिए, मैंने सोचा अगर यह प्रतिबिंब का उपयोग करने के लिए एक बार वर्ग गुण प्राप्त करने के लिए, और फिर उन्हें कैश ताकि मैं गतिशील का मूल्यांकन कर सकता है संभव है ऑब्जेक्ट गुण और मूल्यों को पढ़/असाइन करें, लेकिन जब भी मैं ऐसा करता हूं तो प्रतिबिंब ओवरहेड नहीं होता है। क्या यह संभव है (नमूना कोड?)?कैश प्रतिबिंब परिणाम (कक्षा गुण)

थोड़ा स्पष्ट करने के लिए, मान लीजिए कि मैं इस वर्ग है:

public class Cloud 
{ 
    Boolean IsWhite; 
} 

और अब मैं एक विधि है कि मुझे इस (स्यूडोकोड) की तरह कुछ करने के लिए अनुमति देता है बनाने के लिए कोशिश कर रहा हूँ:

Update(myCloudInstance, new {IsWhite, true}); 

अद्यतन अब पहले कैश के साथ जांचना चाहिए यदि यह क्लाउड (टाइपोफ (myCloudInstance)) के गुणों को पहले से जानता है, और उसके बाद प्रतिबिंबित करने के बजाय "IsWhite" मान को "सत्य" मान निर्दिष्ट करने के लिए कैश की गई जानकारी का उपयोग करें।

यह कैसे करें इस पर कोई विचार है?

उत्तर

7

यह स्पष्ट नहीं है बिल्कुल आप क्या कर रहे हैं, लेकिन कैशिंग निश्चित रूप से प्रतिबिंब के साथ एक अंतर बना सकती है।

विशेष रूप से, अगर आप तरीकों (या संपत्ति getters/setters) लागू कर रहे हैं और जहाँ तक बुला कोड का सवाल है एक प्रकार सुरक्षित तरीके से ऐसा कर सकते हैं, यह can make a huge difference अगर आप MethodInfo एक strongly- में तब्दील टाइप किए गए प्रतिनिधि को एक बार फिर पुन: उपयोग करें।

आप हमें तुम क्या करने की कोशिश कर रहे हैं की एक पूरी उदाहरण दे सकता है, कि हमारी मदद अधिक विशिष्ट अनुमान या यहाँ तक कि कोड के साथ आने के लिए होगा। यदि आप PropertyInfo को कैश करने जा रहे हैं, जिसमें अधिक (या कोई भी) प्रभाव नहीं हो सकता है - यह संभव है कि सामान्य Type.GetProperty (आदि) विधियां पहले से ही बहुत तेज हैं। प्रदर्शन प्रश्नों के साथ, कुंजी यह मापने के लिए है कि आप वास्तव में क्या कर रहे हैं। परिवर्तन करें और फिर से मापने, आदि

+0

आपका उत्तर मुझे सही दिशा में इंगित करता है (PropertyInfo कैश कैसे करें) जो वास्तव में GetProperty से तेज़ है (अभी तक यह समय नहीं है, लेकिन मेरे पृष्ठ की प्रतिक्रिया में सुधार हुआ है।) – Alex

+0

यदि आप संपत्ति को कॉल करने के लिए प्रतिनिधियों को कैश कर सकते हैं प्रकार-सुरक्षित तरीका, जो इसे फिर से तेज़ी से बना सकता है। निश्चित रूप से यह समय हालांकि ... –

2

प्रतिबिंब की लागत के रूप में बड़ी के रूप में आपको लगता है हो सकता है की जरूरत नहीं है। प्रतिनिधियों (जॉन की चर्चा है कि) तुम भी ज्यादा कोड बदले बिना प्रतिबिंब की लागत कम करने HyperDescriptor जैसी चीजों का उपयोग कर सकते करने के अलावा - यह बस PropertyDescriptor बजाय हो जाता है:

PropertyDescriptorCollection props = TypeDescriptor.GetProperties(myCloudInstance); 
// ideally cache props, but not essential 
तो

object val = props["IsWhite"].GetValue(myCloudInstance); 

या यदि आप इसे बहुत उपयोग करते हैं, तो PropertyDescriptor कहीं भी संग्रहीत करने पर विचार करें।

हालांकि ... जॉन की तरह, मैं वास्तव में 100% निश्चित नहीं हूं कि आप क्या करने की कोशिश कर रहे हैं!

0

गतिशील असेंबली प्रतिबिंब प्रदर्शन के बारे में चिंता के साथ मदद करनी चाहिए। किसी ने गतिशील असेंबली here का उपयोग कर संपत्ति निर्धारकों को लागू किया है।

1

मैं सबसे अच्छा तरीका यह, गेटर या सेटर विधि प्राप्त यह एक प्रतिनिधि में बदलने का है, और प्रतिनिधि के साथ काम करने के लिए है करने के लिए लगता है, वहाँ कोई तेज़ तरीका है:

PropertyInfo propertyInfoProperty1 = type.GetType().GetProperty("Property1"); 
Func<TYPE, string> get_Property1 = (Func<TYPE, string>)Delegate.CreateDelegate(typeof(Func<TYPE, string>), propertyInfoProperty1.GetGetMethod()); 

फिर गेटर फोन विधि:

string value = get_Property1(type); 

आप प्रतिनिधियों को कैश कर सकते हैं।

2

मैंने प्रतिबिंब परिणामों को कैश करने के लिए एक हैशटेबल बनाया है। पहली बार, GetProperties को कॉल करने और परिणामों को जल्दबाजी में स्टोर करने के लिए यह आवश्यक नहीं है। अगली बार, पहले PropertyInfo ऑब्जेक्ट्स की सूची के लिए हैशटेबल की जांच करें। यदि मौजूद है, तो इसका इस्तेमाल करें। यदि नहीं, GetProperties का आह्वान करें।

मैं इसका उपयोग एक डाटाएडर को सूची की सूची में मैप करने के लिए करता हूं।

मेरा कार्यान्वयन निक हैरिसन (http://www.simple-talk.com/dotnet/.net-framework/a-defense-of-reflection-in-.net/) द्वारा A Defense on Reflection in .Net पर आधारित है।

तो, वहाँ यह है:

public class MapeadorDataReaderListaObjetos 
{ 

    private Hashtable properties; 

    private Hashtable Properties 
    { 
     get 
     { 
      if (properties == null) 
       properties = new Hashtable(); 
      return properties; 
     } 
     set { properties = value; } 
    } 

    private void LoadProperties(object targetObject, Type targetType) 
    { 
     var flags = BindingFlags.DeclaredOnly| BindingFlags.Instance| BindingFlags.Public; 

     if (properties == null) 
     { 
      List<PropertyInfo> propertyList = new List<PropertyInfo>(); 
      PropertyInfo[] objectProperties = targetType.GetProperties(flags); 
      foreach (PropertyInfo currentProperty in objectProperties) 
      { 
       propertyList.Add(currentProperty); 
      } 
      properties = new Hashtable(); 
      properties[targetType.FullName] = propertyList; 
     } 

     if (properties[targetType.FullName] == null) 
     { 
      List<PropertyInfo> propertyList = new List<PropertyInfo>(); 
      PropertyInfo[] objectProperties = targetType.GetProperties(flags); 
      foreach (PropertyInfo currentProperty in objectProperties) 
      { 
       propertyList.Add(currentProperty); 
      } 
      properties[targetType.FullName] = propertyList; 
     } 
    } 

    public void MapearDataReaderListaObjetos <T> (IDataReader dr, List<T> lista) where T: new() 
    { 
     Type businessEntityType = typeof(T); 
     List<T> entitys = new List<T>(); 
     T miObjeto = new T(); 
     LoadProperties(miObjeto, businessEntityType); 
     List<PropertyInfo> sourcePoperties = Properties[businessEntityType.FullName] as List<PropertyInfo>; 

     while (dr.Read()) 
     { 
      T newObject = new T(); 
      for (int index = 0; index < dr.FieldCount; index++) 
      { 
       for (int _indice = 0; _indice < sourcePoperties.Count; _indice++) 
       { 
        if (sourcePoperties[_indice].Name.ToUpper() == dr.GetName(index).ToUpper()); 
        { 
         string _tipoProp = sourcePoperties[_indice].PropertyType.ToString(); 
         PropertyInfo info = sourcePoperties[_indice] as PropertyInfo; 
         if ((info != null) && info.CanWrite) 
         { 
          info.SetValue(newObject, dr.GetValue(index), null); 
         } 
        } 
       } 
      } 
      entitys.Add(newObject); 
     } 
     dr.Close(); 
     lista = entitys; 
    } 
} 

फिर, मैं इसे अपने DataAcces लेयर से कहते हैं, इस तरह:

public List <Entities.ENFactura> ListaxIdFactura (SqlTransaction Tr, Entities.ENFactura oBEFactura) 
{ 

    SqlConnection Cn = new SqlConnection(); 
    Cn = _Connection.ConexionSEG(); 

    List<Entities.ENFactura> loBEFactura = new List<Entities.ENFactura>(); 

    using (Cn) 
    { 
     Cn.Open(); 
     SqlDataReader drd = (odaSQL.fSelDrd(Cn, Tr, "Pa_CC_Factura_Listar_x_IdProveedor", oBEFactura)); 
     if (drd != null) 
     { 
      if (drd.HasRows) 
      { 
       mapeador.MapearDataReaderListaObjetos <ENFactura>(drd, loBEFactura); 
      } 
     } 
    } 
    return (loBEFactura); 
} 

तो, इस तरह से, दाल किसी DataReader हो जाता है, यह नक्शा व्यापार संस्थाओं की एक सूची में, और इसे व्यापार तर्क परत पर वापस कर दें।

इस वर्ग (MapeadorDataReaderListaObjetos), अभी भी कुछ मुद्दे हैं, विशेष रूप से पर:

info.SetValue(newObject, _valor, null); 

newObject और _valor एक ही प्रकार का होना चाहिए या आप एक अपवाद (System.Int32 को System.Int64 से रूपांतरण मिल जाएगा, यदि आपकी इकाई संपत्ति Int32 है और डेटाबेस तालिका में इसके संबंधित फ़ील्ड को बड़ा है, उदाहरण के लिए)।

इसके अलावा, यदि एक इकाई संपत्ति एक और इकाई है, तो यह काम नहीं करेगा, क्योंकि डेटरेडर इकाई वस्तुओं को वापस नहीं करते हैं।

जाहिर है, यह बेहतर किया जा सकता है।

प्रतिबिंब और प्रतिनिधियों के संबंध में, मुझे यह आलेख मिला: प्रतिबिंब - धीमा या तेज़? समाधान, अभिषेक सुर से साथ प्रदर्शन, http://www.abhisheksur.com/2010/11/reflection-slow-or-faster-demonstration.html

एक और अच्छा लेख पर है: चकमा आम प्रदर्शन नुकसान शीघ्र आवेदन में कांट-छांट करने के लिए, जोएल Pobar द्वारा, http://msdn.microsoft.com/en-us/magazine/cc163759.aspx पर।

उम्मीद है कि इससे मदद मिलती है।

संबंधित मुद्दे