2009-08-27 10 views
12

मुझे "बाएं/दाएं" विधियों का एक समूह होने से नफरत है। प्रत्येक बार जब कोई संपत्ति जोड़ या हटा दी जाती है, तो मुझे प्रत्येक विधि को ठीक करना होगा। और कोड खुद ही दिखता है ... गलत।रचनाकारों और तुलना को सरल बनाने के लिए प्रतिबिंब का उपयोग कैसे करें?

public Foo(Foo other) 
{ 
    this.Bar = other.Bar; 
    this.Baz = other.Baz; 
    this.Lur = other.Lur; 
    this.Qux = other.Qux; 
    this.Xyzzy= other.Xyzzy; 
} 

सच यह सिर्फ एक unrolled पाश कि गुण के माध्यम से दोहराता है, उन्हें वस्तुओं के बीच कॉपी है। तो उस तथ्य के बारे में ईमानदार क्यों नहीं हो? बचाव के प्रति प्रतिबिंब!

public Foo(IFoo other) 
{ 
    foreach (var property in typeof(IFoo).GetProperties()) 
    { 
     property.SetValue(this, property.GetValue(other, null), null); 
    } 
} 

मैं सिर्फ एक प्रतिमान मैं सी # पर लुआ से सीखा के लिए मजबूर करने की कोशिश कर रहा हो सकता है लेकिन इस विशिष्ट उदाहरण मेरे लिए भी बदबूदार प्रतीत नहीं होता। यहां से, मैंने कुछ और जटिल चीजें करना शुरू कर दिया जो खेतों के क्रम में संवेदनशील थे। उदाहरण के लिए, क्षेत्रों से एक स्ट्रिंग की रचना करने के बजाय लगभग समान if बयान के ढेर होने, मैं सिर्फ उन पर वांछित क्रम में पुनरावृति:

public override string ToString() 
{ 
    var toJoin = new List<string>(); 
    foreach (var property in tostringFields) 
    { 
     object value = property.GetValue(this, null); 
     if (value != null) 
      toJoin.Add(value.ToString()); 
    } 
    return string.Join(" ", toJoin.ToArray()); 
} 
private static readonly PropertyInfo[] tostringFields = 
{ 
    typeof(IFoo).GetProperty("Bar"), 
    typeof(IFoo).GetProperty("Baz"), 
    typeof(IFoo).GetProperty("Lur"), 
    typeof(IFoo).GetProperty("Qux"), 
    typeof(IFoo).GetProperty("Xyzzy"), 
}; 

तो अब मैं iterability मैं चाहता था है, लेकिन मैं अभी भी मेरे द्वारा रुचि रखने वाली प्रत्येक संपत्ति को प्रतिबिंबित करने वाले कोड के ढेर हैं (मैं अलग-अलग क्रम में गुणों के एक अलग सेट का उपयोग करके तुलना करने के लिए भी कर रहा हूं)। इससे भी बदतर मजबूत टाइपिंग का नुकसान है। यह वास्तव में गंध शुरू कर रहा है।

अच्छी तरह से आदेश को परिभाषित करने के लिए प्रत्येक संपत्ति पर विशेषताओं का उपयोग करने के बारे में क्या? मैंने इस सड़क को शुरू कर दिया और वास्तव में यह अच्छी तरह से काम किया, लेकिन यह सिर्फ पूरी चीज फूला हुआ देखा। यह बहुत ही महत्वपूर्ण रूप से काम करता है, लेकिन मैं हमेशा उन्नत सुविधाओं का उपयोग करने से सावधान हूं क्योंकि वे "साफ" हैं। इस तरह से overkill में प्रतिबिंब का उपयोग कर रहा है? क्या मुझे याद आ रही बाएं/दाएं कोड की समस्या का कोई अन्य समाधान है?

+0

एक भाषा टैग को जोड़ने के i'dd प्राप्त करने के लिए अधिक दर्शकों – Toad

+0

ध्यान रखें, प्रतिबिंब हमेशा सी # में एक प्रदर्शन हिट के साथ आता है। आप इस तरह फूओस कितनी बार छेड़छाड़ करेंगे? प्रतिबिंब का उपयोग करने के लिए एक हाइब्रिड समाधान हो सकता है। प्रवेश करें, और परिणामस्वरूप कोड कैश करें - धीमी स्टार्टअप, तेज़ निष्पादन। – zildjohn01

+1

सी # 4.0 संकलक में बनाया के साथ आ रहे हैं, कि कोड को पैदा करने में मददगार हो सकता है और इसका इस्तेमाल कर सकते हैं, अब हम भी इसी तरह की समस्या है, लेकिन हम एक्सएमएल कक्षा संरचनाओं का उपयोग करके समाधान बनाया गया है और हम अपने ही कोड पीढ़ी विधि का उपयोग वर्गों है कि होगा निर्माण करने के लिए के लिए है कई अन्य विधियों को उत्पन्न करें जो memebers के नाम पर निर्भर हैं, इसकी मूल रूप से एक ORML है लेकिन सब कुछ स्वचालित करता है। –

उत्तर

5

प्रतिबिंब का उपयोग करना और स्वयं का उपयोग करना बुरा नहीं है, लेकिन आप प्रदर्शन प्रदर्शन करेंगे, खासकर यदि आप इसे बार-बार करते हैं।

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

या पूरा आप क्या चाहते हैं, मार्क Gravells Hyper Property Descriptor सहित अन्य तरीकों से कर रहे हैं आप कुछ आईएल और opcodes आप System.Reflection.Emit उपयोग कर सकते हैं या यहां तक ​​कि Cecil from Mono जानने के लिए चाहते हैं।

यहाँ है कि आप संभवतः अपनी आवश्यकताओं के दर्जी कर सकते हैं हाइपर संपत्ति डिस्क्रिप्टर का उपयोग करने का एक उदाहरण है:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using Hyper.ComponentModel; 
namespace Test { 
    class Person { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 
    class Program { 
     static void Main() { 
      HyperTypeDescriptionProvider.Add(typeof(Person)); 
      var properties = new Dictionary<string, object> { { "Id", 10 }, { "Name", "Fred Flintstone" } }; 
      Person person = new Person(); 
      DynamicUpdate(person, properties); 
      Console.WriteLine("Id: {0}; Name: {1}", person.Id, person.Name); 
      Console.ReadKey(); 
     } 
     public static void DynamicUpdate<T>(T entity, Dictionary<string, object> { 
      foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(typeof(T))) 
       if (properties.ContainsKey(propertyDescriptor.Name)) 
        propertyDescriptor.SetValue(entity, properties[propertyDescriptor.Name]); 
     } 
    } 
} 

आप प्रतिबिंब का उपयोग पर ले जाने का फैसला करते हैं, तो आप प्रदर्शन GetProperties करने के लिए अपने कॉल कैशिंग ने टक्कर मार दी कम कर सकते हैं () तो जैसे:

public Foo(IFoo other) { 
    foreach (var property in MyCacheProvider.GetProperties<IFoo>()) 
     property.SetValue(this, property.GetValue(other, null), null); 
} 
+3

टाइप। गेटप्रॉपर्टीज पहले से ही अपना कैशिंग (पहली बार कॉल और बाद की कॉल) करता है। प्रतिबिंब का असली प्रदर्शन हिट संपत्ति है। सैटवैल्यू कॉल, जिसे आप एमएसआईएल पीढ़ी आदि के साथ कम कर सकते हैं –

+0

@ रोब फोन्सेका-एन्सर धन्यवाद, मुझे यह नहीं पता था। – grenade

+0

हम्म ... यदि प्रदर्शन हिट मूल्यों को सेट करने में है तो शायद यह जाने का तरीका नहीं है। उन सभी निम्न-स्तरीय सामानों से निपटने का प्रयास करना निश्चित रूप से अधिक होगा। इनपुट के लिए धन्यवाद। – Cogwheel

2

IMHO, प्रतिबिंब सी # का एक बहुत ही शक्तिशाली सुविधा है, लेकिन जो बहुत एक फूला हुआ कोड में परिणाम की संभावना है, और जो कोड की सीखने की अवस्था के लिए बहुत कुछ कहते हैं और रख-रखाव कम कर देता है। आपको गलतियों को करने की अधिक संभावना होगी (एक बार मूल रिफैक्टरिंग त्रुटियों का कारण बन सकती है), और किसी भी संपत्ति के नाम को बदलने से अधिक डरते हैं (यदि आपको बेहतर नाम मिलना है) या ऐसी चीजें।

मेरे पास व्यक्तिगत रूप से एक ही समस्या के साथ एक कोड है, और मुझे ऑर्डर और इत्यादि बनाए रखने के लिए विशेषताओं को जोड़ने का एक ही विचार था। लेकिन मेरी टीम (मेरे साथ) ने सोचा कि डिज़ाइन को बदलने के लिए कुछ समय खोना बेहतर होगा इस। शायद यह समस्या खराब डिजाइन के कारण होती है (ठीक है, यह मेरे मामले में था, लेकिन मैं इसे आपके बारे में नहीं बता सकता)।

+0

मुझे यकीन नहीं है कि गुणों को बदलते समय यह और अधिक त्रुटि-प्रवण होगा क्योंकि संपूर्ण बिंदु कोड में सीधे संपत्ति नामों को संदर्भित करने की आवश्यकता को खत्म करना है। अभी मैं एक डोमेन मॉडल बना रहा हूं जिसे अंततः डेटाबेस में मैप किया जाएगा, इसलिए विकास के दौरान गुणों को जोड़ना/निकालना/नामकरण करना लगभग विशेष रूप से गैर-स्टॉप होगा (विशेष रूप से जब से मैं पहली बार टीडीडी का प्रयास कर रहा हूं) – Cogwheel

+0

आपके पास आपके कोड में टाइप टाइप (आईएफयू) .GetProperty ("Bar") "है, जो संदर्भ नामों का संदर्भ सीधे –

+0

है इसलिए मेरे प्रश्न में पिछले दो पैराग्राफ;) – Cogwheel

3

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

पुस्तकालय AutoMapper कहा जाता है और यह एक और करने के लिए एक वस्तु से नक्शे और गतिशील रूप से मक्खी पर एक आईएल विधानसभा बनाने के द्वारा ऐसा नहीं करता है। इससे यह सुनिश्चित होता है कि एक पहली बार हिट के अलावा, आप बेहतर प्रदर्शन मिलता है और अपने कोड बहुत सरल होगा:

public Foo(Foo other) 
{ 
    Mapper.Map(other, this); 
} 

यह महान काम करने के लिए जाता है और यहाँ का आविष्कार नहीं किया जा रहा का जोड़ा बोनस है, जो मैं एक हूँ है का प्रशंसक।

मैं कुछ निष्पादन परीक्षण किया था और 20 एमएस (अभी भी बहुत तेजी से) की पहली हिट के बाद इसके बारे में के रूप में 0 के करीब के रूप में आप प्राप्त कर सकते हैं था। बहुत प्रभावशाली।

उम्मीद है कि यह किसी की मदद करेगा।

+0

या आप एमिटमैपर का उपयोग कर सकते हैं जो कि तेज़ है। –

+0

मुझे नहीं लगता कि emitmapper '09 में उपलब्ध था जब मैंने इसे सबमिट किया :) –

+0

अच्छा ... यह आपके उत्तर में सुधार करने में कभी देर नहीं हुई है :) –

2

मूल समस्या आप की तरह एक गतिशील रूप से एक टाइप किया एक स्थिर टाइप किया भाषा का उपयोग करने की कोशिश कर रहे है।

वहाँ वास्तव में कुछ भी कल्पना के लिए एक की जरूरत नहीं है। यदि आप गुणों को पुन: सक्रिय करने में सक्षम होना चाहते हैं, तो आप अपनी कक्षा में सभी गुणों के लिए बैकिंग स्टोर के रूप में मानचित्र <> का उपयोग कर सकते हैं।

संयोग से यह आपके लिए वास्तव में कैसे वी.एस. परियोजना जादूगर implmements एप्लिकेशन सेटिंग है। (System.Configuration.ApplicationSettingsBase देखें) इसकी भी बहुत 'lua की तरह'

public bool ConfirmSync { 
     get { 
      return ((bool)(this["ConfirmSync"])); 
     } 
     set { 
      this["ConfirmSync"] = value; 
     } 
    } 
+0

अच्छा! बहुत ही रोचक रणनीति। यह आपको बैकिंग स्टोर पर लूप करने और एक बहुत ही सरल लूप में सब कुछ कॉपी करने की अनुमति देगा। बहुत आविष्कारक –

+0

टिप के लिए धन्यवाद। मैं शायद इस बिंदु पर इसका उपयोग कर समाप्त कर दूंगा, लेकिन यह मेरे वर्तमान कार्य के लिए बिल्कुल सही नहीं है। – Cogwheel

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

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