12

実行時に属性のパラメータを変更する必要があります。問題を簡単な例に単純化しました。

属性クラス:

    [AttributeUsage(AttributeTargets.Property)]
    public class MyAttribute : Attribute
    {
        public string Name { get; set; }
    }

プロパティを属性で装飾した単純なエンティティ:

    public class MyEntity
    {
        [MyAttribute(Name="OldValue1")]
        public string Data1{ get; set; }

        [MyAttribute(Name = "OldValue2")]
        public string Data2 { get; set; }
    }

MyEntityクラスのインスタンスを作成しました。オブジェクトのプロパティの値を変更することはできますが、オブジェクトエンティティの属性のプロパティNameの値を変更することはできません。出来ますか?

オブジェクトエンティティのプロパティの値コードのこの部分で変更できます。

                entityProp.SetValue(entity,"NewData",null);

しかし、オブジェクトエンティティの属性のプロパティNameの値を変更する方法はありません

これは動作しません:

attProp.SetValue(attribute,"NewData",null);

プロパティNameの値は元のままです。

これがすべてのテストコードです。

    [TestMethod]
    public  void Test()
    {
        var entity = new MyEntity
                         {
                             Data1 = "OldData",
                             Data2 = "OldData"
                         };

        PropertyInfo[] entityProps = entity.GetType().GetProperties();

        foreach (var entityProp in entityProps)
        {
            var attribute = Attribute.GetCustomAttribute(entityProp, typeof (MyAttribute)) as MyAttribute;

            if (attribute != null)
            {
                //get attribute's property NAME
                PropertyInfo attProp= attribute.GetType().GetProperty("Name");

                //get entity property value
                var propertyValue = entityProp.GetValue(entity, null);

                //get attribute’s property NAME value
                var atributeNameValue = attProp.GetValue(entity, null);

                TestContext.WriteLine(string.Format("property name:{0} property value: {1} : atribute name value: {2}\n", 
                    entityProp.Name, propertyValue, atributeNameValue)); 

                //change values
                entityProp.SetValue(entity,"NewData",null);

                //how can I change value of property Name on object entity ?
                attProp.SetValue(attribute,"NewData",null);
                
            }

        }

        TestContext.WriteLine(string.Format("After change\n"));

        foreach (var entityProp in entityProps)
        {
            var attribute = Attribute.GetCustomAttribute(entityProp, typeof(MyAttribute)) as MyAttribute;

            if (attribute != null)
            {

                PropertyInfo attProp = attribute.GetType().GetProperty("Name");

                var propertyValue = entityProp.GetValue(entity, null);
                var atributeNameValue = attProp.GetValue(entity, null);

                TestContext.WriteLine(string.Format("property name:{0} property value: {1} : atribute name value: {2}\n",
                    entityProp.Name, propertyValue, atributeNameValue));
            }
        }
    }

編集済み:元の投稿を削除し、非常に単純な明確なサンプルを追加しました。ごめん

4

2 に答える 2

12

実行時に属性を変更することはできません。それらは、アセンブリのメタデータに埋め込まれています。あなたのメソッドは特定のインスタンスの内部状態を変更しています。ただし、属性を再度ロードすると、別のインスタンスが取得されます。

于 2012-04-06T18:03:45.163 に答える
5

(すでに述べたように)メタデータは固定されているため、これはリフレクションでは不可能です。ただし、実行時に属性を追加および置換し、完全な代替モデル(TypeDescriptionProviderなど)を提供できるTypeDescriptorを使用すると、部分的に可能になります。このアプローチは、リフレクションを使用するコードでは尊重されませんが、TypeDescriptorを使用するコード(最も一般的には、データバインディングやその他のUIコード)は変更に気付くでしょう。

注TypeDescriptorは、typ/memberごとに各属性タイプの1つでのみ実際に機能します。マルチインスタンス属性は十分にサポートされていません。

于 2012-04-06T18:14:45.227 に答える