How to add an attribute to a property at runtime

C#Attributes

C# Problem Overview


//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

C# Solutions


Solution 1 - C#

Don't let someone tell you that you can't do it. You can run for president if you want :-)

For your convenience, 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");
}

Solution 2 - C#

Use FastDeepCloner which I developed.

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>();

Solution 3 - C#

Sorry, I'm very late to the party. This is for those who might come here later. The top answer is awesome. Recently, a library has been developed, that abstracts away all of that complexity, and gives you something as simple as this:

var attributeType = typeof(CustomAAttribute);
var attributeParams = new object[] { "Jon Snow" };
var typeExtender = new TypeExtender("ClassA");
typeExtender.AddProperty("IsAdded", typeof(bool), attributeType, attributeParams);

To work with. details of how to install and use the library can be found here

Disclaimer: I developed this library and I've been using it for a lot of projects and it works like magic

Solution 4 - C#

It is not working because the FillAttributes method expects a parameter of the IList type and you are passing an array. Below is the implementation of 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 the var attributes= new ValidationAttribute[]{attribute}; line with:

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 a type at runtime which is based on an already existing type.

Solution 5 - C#

It is not possible to add Attributes in run-time. Attributes are static and cannot be added or removed.

Similar questions:

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionThiru kumaranView Question on Stackoverflow
Solution 1 - C#Jürgen SteinblockView Answer on Stackoverflow
Solution 2 - C#Alen.TomaView Answer on Stackoverflow
Solution 3 - C#Ndubuisi JrView Answer on Stackoverflow
Solution 4 - C#Alexander ManekovskiyView Answer on Stackoverflow
Solution 5 - C#ArtlessView Answer on Stackoverflow