如何在运行时向属性添加属性
本文关键字:属性 添加 运行时 | 更新日期: 2023-09-27 17:57:03
//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 });
嗨,我正在尝试使用上面的代码在运行时添加验证属性。但是,我收到以下异常:
收藏是固定大小的
不要让别人告诉你你做不到。如果你愿意,你可以竞选总统:-)
为了您的方便,这是一个完全工作的示例
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");
}
顶部答案很棒。最近,开发了一个库,它抽象了所有这些复杂性,并为您提供了这样简单的东西:
var attributeType = typeof(CustomAAttribute);
var attributeParams = new object[] { "Jon Snow" };
var typeExtender = new TypeExtender("ClassA");
typeExtender.AddProperty("IsAdded", typeof(bool), attributeType, attributeParams);
有关如何安装和使用库的详细信息,请参阅此处
免责声明:我开发了这个库,我一直在很多项目中使用它,它就像魔术一样工作
使用我开发的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>();
它
不起作用,因为FillAttributes
方法需要 IList 类型的参数,并且您正在传递一个数组。下面是 MemberDescriptor.FillProperties 的实现:
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
添加属性",除非您尝试在运行时构建基于现有类型的类型,否则没有任何意义。
无法在运行时添加属性。属性是静态的,无法添加或删除。
类似问题:
- 是否可以在 C# 中动态添加属性?
- 动态删除属性的 C# 属性