2013-02-02 114 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

可能重複的屬性可以動態地在增加C#?](http://stackoverflow.com/questions/129285/can-attributes-be-added-dynamically-in-c) –

回答

0

它不工作呢,因爲FillAttributes方法需要IList的類型的參數,以及要傳球達陣。下面是執行MemberDescriptor.FillAttributes

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

正如你可以看到FillAttributes剛好充滿attributeList參數與你的財產的所有屬性。而爲了讓你的代碼工作變動var attributes= new ValidationAttribute[]{attribute};符合:

var attributes = new ArrayList { attribute }; 

此代碼有沒有在運行時添加屬性類型的屬性。這是「將屬性添加到PropertyDescriptor」,從類型中提取並且沒有意義,除非您嘗試在基於已有類型的運行時構建類型。

80

不要讓別人告訴你,你不能這樣做。如果你想:-)

爲了您爲了方便地可以競選總統,這是一個完全工作的例子

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

我從Deez堅果中學到的東西是,在運行時爲屬性添加一個屬性比較困難:-) –

+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>(); 
的[
相關問題