2010-05-06 16 views
12

बिना तार के माध्यम से गुण का उपयोग करने की गतिशील कीवर्ड का उपयोग करते हुए # मैं निम्न जैसा कुछ लिखने के लिए करना चाहते हैं:सी प्रतिबिंब

// I will pass in a number of "properties" specified as strings that I want modified 
string[] properties = new [] { "AllowEdit", "AllowDelete" }; 

// Casting the component I'm using to a dynamic object of some sort ? 
dynamic d = myGridComponent; 

// Iterate over the strings and set the properties 
foreach(var s in properties) 
{ 
    //d.s = true; // 
    //d[s] = true; // this format would be ideal 
} 

अगर वहाँ प्रतिबिंब का उपयोग किए बिना ऐसा करने के लिए [.GetProperty(...).GetValue(...,...) एक आसान तरीका था मैं सोच रहा था ] नए सी # 4.0 कीवर्ड का उपयोग कर: dynamic

ऐसा लगता है कि कुछ रास्ता हो सकता है ... मैं बिल्कुल सटीक तंत्र के बारे में निश्चित नहीं हूं, और सभी टुकड़ों को एक साथ रखने के लिए सही संसाधन नहीं ढूंढ पा रहा हूं।

विचार?

[संपादित करें] ऐसा लगता है कि "क्ले" नामक एक पैकेज है जो इस तरह की कार्यक्षमता को किसी तरह से लागू करता है। Clay on CodePlex
Scott Hanselman on the Subject

उत्तर

6

यह किया जा सकता है। आपको DynamicObject पर TryGetIndex ओवरराइड करना होगा। मुझे किसी प्रकार के स्थिर सदस्यों को आमंत्रित करने के समान कुछ चाहिए, लेकिन उम्मीद है कि आपको यह विचार मिल जाएगा। ध्यान रहे कि आप इस वर्तमान में, सामान्य प्रकार तर्क या तरीकों कि अतिभारित रहे हैं के साथ तरीकों पर काम नहीं करता है इसकी उपयोगिता सीमित:

internal class StaticMembersDynamicWrapper : DynamicObject 
{ 
    private readonly IDictionary<String, MemberInfo> staticMembers = new Dictionary<string, MemberInfo>(); 
    private readonly Type type; 

    public StaticMembersDynamicWrapper(Type type) 
    { 
     this.type = type; 
     type.GetMembers(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public) 
      .Each(member => staticMembers[member.Name] = member); 
    } 

    public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) 
    { 
     var name = indexes[0] as string; 

     MemberInfo member; 

     if (false == staticMembers.TryGetValue(name, out member)) 
     { 
      result = null; 
      return false; 
     } 

     var prop = member as PropertyInfo; 
     if (prop != null) 
     { 
      result = prop.GetValue(null, null); 
      return true; 
     } 
     var method = member as MethodInfo; 
     if (method != null) 
     { 
      var parameterTypes = (from p in method.GetParameters() 
            select p.ParameterType).ToArray(); 
      var delegateType = method.ReturnType != typeof (void) 
          ? Expression.GetFuncType(parameterTypes.Union(new[]{method.ReturnType}).ToArray()) 
          : Expression.GetActionType(parameterTypes); 
      result = Delegate.CreateDelegate(delegateType, method); 
      return true; 
     } 
     result = null; 
     return false; 
    } 
} 

dynamic d = new StaticMembersDynamicWrapper(typeof(string)); 
var result = d["IsNullOrEmpty"](String.Empty); 
+0

वाह वास्तव में अच्छा समाधान, मैं इस सटीक चीज़ की तलाश में था! –

3

सी # में नंबर dynamic कि प्रदान नहीं करता है। अपने दो उदाहरण के साथ:

d.s = true; // this looks for a property or field called "s" 
d[s] = true; // this looks for an indexer that matches the string/bool signature 

आप एक ही कोड है कि dynamic प्रदान करता है लिख सकते हैं, लेकिन यह सिर्फ प्रतिबिंब का उपयोग की तुलना में बहुत कठिन होगा। या तो प्रतिबिंब का उपयोग करें (आपके उदाहरण के अनुसार), या यदि आपको इसे अनुकूलित करने की आवश्यकता है तो आप इसे Expression या Delegate.CreateDelegate के माध्यम से वैकल्पिक रूप से किसी प्रतिनिधि में लपेट सकते हैं।

+0

ऐसा नहीं सोचा, लेकिन पूछने लायक! निश्चित रूप से एक फीचर जो मुझे PHP से याद आती है .. बेशक, कम से कम * * इसे करने के तरीके हैं, बस सोचा कि यह अच्छा होगा अगर गतिशील वस्तुओं को इंडेक्सर के माध्यम से एक्सेस किया जा सके। :) - मैथ्यू –

2

ओपनसोर्स ढांचे Impromptu-interface nuget के माध्यम से उपलब्ध कोड है कि गतिशील एक पूरी तरह से गतिशील फैशन में उत्पन्न होगा समाहित। यह गतिशील कीवर्ड का उपयोग करने जितना तेज़ नहीं है, लेकिन faster than reflection है।

foreach(var s in properties) 
{ 
    //d.s = true; 
    Impromptu.InvokeSet(d, s, true); 
} 
+0

वास्तव में बहुत अच्छा काम किया, धन्यवाद। –

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