C# 如何在运行时向属性添加属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14663763/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to add an attribute to a property at runtime
提问by Thiru kumaran
//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 });
Hi I am trying to add Validation attribute at runtime using the above code. However I am getting the below exception:
嗨,我正在尝试使用上述代码在运行时添加验证属性。但是我收到以下异常:
Collection was of a fixed size
集合具有固定大小
回答by Artless
It is not possible to add Attributes in run-time. Attributes are static and cannot be added or removed.
无法在运行时添加属性。属性是静态的,不能添加或删除。
Similar questions:
类似问题:
回答by Alexander Manekovskiy
It is not wokring because FillAttributes
method expects parameter of IList type and you are passing array. Below is implementation of MemberDescriptor.FillAttributes:
这不是工作,因为FillAttributes
方法需要 IList 类型的参数并且您正在传递数组。下面是MemberDescriptor.FillAttributes 的实现:
protected virtual void FillAttributes(IList attributeList) {
if (originalAttributes != null) {
foreach (Attribute attr in originalAttributes) {
attributeList.Add(attr);
}
}
}
As you can see FillAttributes
just fills the attributeList
parameter with all attributes of your property. And to make your code work change var attributes= new ValidationAttribute[]{attribute};
line with:
如您所见,FillAttributes
只用attributeList
您的属性的所有属性填充参数。并使您的代码工作更改var attributes= new ValidationAttribute[]{attribute};
为:
var attributes = new ArrayList { attribute };
This code has nothing with adding attributes to property of type at runtime. This is "adding attribute to the PropertyDescriptor
" extracted from type and has no sense unless you are trying to build type at runtime which is based on already existing type.
此代码与在运行时向 type 属性添加属性无关。这是“向PropertyDescriptor
从类型中提取的”添加属性,除非您尝试在运行时构建基于现有类型的类型,否则没有任何意义。
回答by Jürgen Steinblock
Don't let someone tell you that you can't do it. You can run for president if you want :-)
不要让别人告诉你你做不到。如果你愿意,你可以竞选总统:-)
For your conveniance, this is a fully working example
为了您的方便,这是一个完整的示例
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");
}
回答by Alen.Toma
use FastDeepCloner
public class test{
public string Name{ get; set; }
}
var prop = DeepCloner.GetFastDeepClonerProperties(typeof(test)).First();
prop.Attributes.Add(new JsonIgnoreAttribute());
// now test and se if exist
prop = DeepCloner.GetFastDeepClonerProperties(typeof(test)).First();
bool containAttr = prop.ContainAttribute<JsonIgnoreAttribute>()
// or
JsonIgnoreAttribute myAttr = prop.GetCustomAttribute<JsonIgnoreAttribute>();