web-dev-qa-db-fra.com

Comment ajouter un attribut à une propriété au moment de l'exécution

//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 });

Salut, j'essaie d'ajouter l'attribut de validation lors de l'exécution en utilisant le code ci-dessus. Cependant, je reçois l'exception ci-dessous:

La collection était de taille fixe

49
Thiru kumaran

Ne laissez personne vous dire que vous ne pouvez pas le faire. Vous pouvez vous présenter aux élections présidentielles si vous le souhaitez :-)

Pour votre convenance, ceci est un exemple pleinement fonctionnel

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

}
135
Jürgen Steinblock

utilisez 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>();
3
Alen.Toma

Ce n'est pas wokring car la méthode FillAttributes attend un paramètre de type IList et vous passez un tableau. Voici l'implémentation de MemberDescriptor.FillAttributes :

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

Comme vous pouvez le voir, FillAttributes remplit simplement le paramètre attributeList avec tous les attributs de votre propriété. Et pour que votre code fonctionne, changez var attributes= new ValidationAttribute[]{attribute}; aligner avec:

var attributes = new ArrayList { attribute };

Ce code n'a rien avec l'ajout d'attributs à la propriété de type lors de l'exécution. C'est "ajouter un attribut au PropertyDescriptor" extrait du type et n'a aucun sens à moins que vous n'essayiez de créer un type au moment de l'exécution basé sur un type déjà existant.

0