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

こんにちは、上記のコードを使用して実行時に Validation 属性を追加しようとしています。ただし、以下の例外が発生しています。

コレクションは固定サイズでした

4

5 に答える 5

195

できないなんて誰かに言わせてはいけません。必要に応じて大統領に立候補できます:-)

便宜上、これは完全に機能する例です

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");
}
于 2014-06-25T15:40:26.220 に答える
5

すみません、パーティーにとても遅れてしまいました。これは後でここに来るかもしれない人のためのものです。一番上の答えは素晴らしいです。最近、その複雑さをすべて抽象化し、次のような単純なものを提供するライブラリが開発されました。

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

一緒に働く。ライブラリのインストール方法と使用方法の詳細については、こちらを参照してください。

免責事項:私はこのライブラリを開発し、多くのプロジェクトで使用してきましたが、魔法のように機能します

于 2020-12-18T15:14:06.003 に答える
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であり、既存の型に基づいて実行時に型を構築しようとしない限り意味がありません。

于 2013-02-02T18:59:44.867 に答える
-13

実行時に属性を追加することはできません。属性は静的であり、追加または削除できません。

同様の質問:

于 2013-02-02T17:05:08.027 に答える