2013-02-02 16 views
33
//Get PropertyDescriptor object for the given property name 
var propDesc = TypeDescriptor.GetProperties(typeof(T))[propName]; 

//Get FillAttributes methodinfo delegate 
var methodInfo = propDesc.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | 
                 BindingFlags.NonPublic) 
    .FirstOrDefault(m => m.IsFamily || m.IsPublic && m.Name == "FillAttributes"); 

//Create Validation attribute 
var attribute = new RequiredAttribute(); 
var attributes= new ValidationAttribute[]{attribute}; 

//Invoke FillAttribute method 
methodInfo.Invoke(propDesc, new object[] { attributes }); 

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

संग्रह एक निश्चित आकार

+0

संभव डुप्लिकेट विशेषताओं में गतिशील रूप से जोड़ा जा सकता है सी #?] (Http://stackoverflow.com/questions/129285/can-attributes-be-added- गतिशील-in-c) –

उत्तर

0

यह wokring नहीं है, क्योंकि FillAttributes विधि IList प्रकार के पैरामीटर की उम्मीद है और आप सरणी से गुजर रहे हैं।

protected virtual void FillAttributes(IList attributeList) { 
    if (originalAttributes != null) { 
     foreach (Attribute attr in originalAttributes) { 
      attributeList.Add(attr); 
     } 
    } 
} 

आप FillAttributes देख सकते हैं सिर्फ अपनी संपत्ति की सभी विशेषताओं के साथ attributeList पैरामीटर भरता है: नीचे MemberDescriptor.FillAttributes का कार्यान्वयन है। और अपने कोड काम के साथ var attributes= new ValidationAttribute[]{attribute}; लाइन बदलने के बनाने के लिए:

var attributes = new ArrayList { attribute }; 

इस कोड को कार्यावधि में प्रकार की संपत्ति के गुण को जोड़ने के साथ कुछ भी नहीं है। यह "PropertyDescriptor पर विशेषता जोड़ रहा है" टाइप से निकाला गया है और इसका कोई मतलब नहीं है जब तक कि आप रनटाइम पर टाइप बनाने की कोशिश नहीं कर रहे हैं जो पहले से मौजूद प्रकार पर आधारित है।

80

किसी को आपको बताने न दें, आप इसे नहीं कर सकते हैं। आप :-)

अपने conveniance के लिए चाहते हैं तो आप राष्ट्रपति के लिए चला सकते हैं, यह एक पूरी तरह से काम कर रहे उदाहरण है

public class SomeAttribute : Attribute 
    { 
     public SomeAttribute(string value) 
     { 
      this.Value = value; 
     } 

     public string Value { get; set; } 
    } 

    public class SomeClass 
    { 
     public string Value = "Test"; 
    } 

    [TestMethod] 
    public void CanAddAttribute() 
    { 
     var type = typeof(SomeClass); 

     var aName = new System.Reflection.AssemblyName("SomeNamespace"); 
     var ab = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run); 
     var mb = ab.DefineDynamicModule(aName.Name); 
     var tb = mb.DefineType(type.Name + "Proxy",System.Reflection.TypeAttributes.Public, type); 

     var attrCtorParams = new Type[] { typeof(string) }; 
     var attrCtorInfo = typeof(SomeAttribute).GetConstructor(attrCtorParams); 
     var attrBuilder = new CustomAttributeBuilder(attrCtorInfo, new object[] { "Some Value" }); 
     tb.SetCustomAttribute(attrBuilder); 

     var newType = tb.CreateType(); 
     var instance = (SomeClass)Activator.CreateInstance(newType); 

     Assert.AreEqual("Test", instance.Value); 
     var attr = (SomeAttribute)instance.GetType().GetCustomAttributes(typeof(SomeAttribute), false).SingleOrDefault(); 
     Assert.IsNotNull(attr); 
     Assert.AreEqual(attr.Value, "Some Value"); 

    } 
+23

प्रेरक बोलने के लिए अंगूठे! – Sjoerd222888

+1

मैंने डीज़ नट्स से जो सीखा वह यह है कि रनटाइम पर किसी संपत्ति को एक विशेषता जोड़ना कठिन होता है :-) –

+1

हम्म, ऐसा लगता है कि हम इस तकनीक का उपयोग एनम सदस्यों के लिए नहीं कर सकते हैं। मुझे यह कहते हुए एक त्रुटि मिलती है कि अभिभावक वर्ग को सील कर दिया गया है ... – Jerther

0

उपयोग FastDeepCloner

public class test{ 
public string Name{ get; set; } 
} 

var prop = now DeepCloner.GetFastDeepClonerProperties(typeof(test)).First(); 
prop.Attributes.Add(new JsonIgnoreAttribute()); 
// now test and se if exist 
prop = now DeepCloner.GetFastDeepClonerProperties(typeof(test)).First(); 
bool containAttr = prop.ContainAttribute<JsonIgnoreAttribute>() 
// or 
JsonIgnoreAttribute myAttr = prop.GetCustomAttribute<JsonIgnoreAttribute>(); 
की [