149

実行時に属性を追加したり、実行時に属性の値を変更したりすることはできますか?

4

10 に答える 10

71

これは、正確に何を達成しようとしているかによって異なります。

System.ComponentModel.TypeDescriptorのものを使用して、型、プロパティ、およびオブジェクト インスタンスに属性を追加できますが、それらのプロパティを取得するためにも使用する必要があるという制限があります。これらの属性を使用するコードを作成していて、それらの制限内で生活できる場合は、間違いなくそれをお勧めします。

私の知る限り、BCL で TypeDescriptor を使用するのは、PropertyGrid コントロールとビジュアル スタジオ デザイン サーフェイスだけです。実際、彼らが本当にしなければならないことの約半分は、この方法で行っています。

于 2008-09-24T19:35:44.017 に答える
67

属性は静的メタデータです。アセンブリ、モジュール、型、メンバー、パラメーター、および戻り値は、C# のファースト クラス オブジェクトではありません (たとえば、System.Typeクラスは単に型の反映された表現です)。型の属性のインスタンスを取得し、書き込み可能な場合はプロパティを変更できますが、型に適用される属性には影響しません。

于 2008-09-24T19:31:42.857 に答える
11

まあ、違いますが、Reflection.Emit を使用してそうする方法について言及している記事を見つけました。

リンクは次のとおりです: http://www.codeproject.com/KB/cs/dotnetattributes.aspx、可能なアプローチが議論されているため、記事の下部にあるコメントのいくつかも調べたいと思うでしょう。

于 2008-09-24T19:37:38.287 に答える
11

できません。1 つの回避策として、実行時に派生クラスを生成し、属性を追加することが考えられますが、これはおそらくやり過ぎです。

于 2008-09-24T19:31:10.737 に答える
4

いいえ、ちがいます。

属性はメタデータであり、コンパイルされたアセンブリにバイナリ形式で格納されます(これが、属性で単純な型のみを使用できる理由でもあります)。

于 2008-09-24T19:28:22.990 に答える
3

私はそうは思わない。私が間違っていたとしても、あなたが望むことができる最善のことは、タイプのインスタンスではなく、タイプ全体にそれらを追加することです。

于 2008-09-24T19:27:18.517 に答える
3

動的に追加できるものが必要な場合、c# 属性は適していません。データをxmlに保存することを検討してください。私は最近、属性を使用して開始したプロジェクトを行いましたが、最終的には xml を使用したシリアル化に移行しました。

于 2008-09-24T19:31:50.080 に答える
3

なぜあなたはする必要があるのですか?属性はリフレクションのための追加情報を提供しますが、必要なプロパティが外部的にわかっている場合は、属性は必要ありません。

メタデータを外部のデータベースまたはリソース ファイルに比較的簡単に保存できます。

于 2008-09-24T19:32:12.903 に答える
1

以下の Deczaloth のコメントで述べたように、メタデータはコンパイル時に修正されると思います。GetType() をオーバーライドする動的オブジェクトを作成するか、GetCustomType() を使用して独自の型を作成することで、これを実現しています。これを使用すると、次のことができます...

私は System.ComponentModel.TypeDescriptor で非常に努力しましたが、成功しませんでした。それは機能しないという意味ではありませんが、そのためのコードを見たいと思います。

反対に、いくつかの属性値を変更したかったのです。その目的のためにうまく機能する2つの機能を実行しました。

        // ************************************************************************
        public static void SetObjectPropertyDescription(this Type typeOfObject, string propertyName,  string description)
        {
            PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
            var att = pd.Attributes[typeof(DescriptionAttribute)] as DescriptionAttribute;
            if (att != null)
            {
                var fieldDescription = att.GetType().GetField("description", BindingFlags.NonPublic | BindingFlags.Instance);
                if (fieldDescription != null)
                {
                    fieldDescription.SetValue(att, description);
                }
            }
        }

        // ************************************************************************
        public static void SetPropertyAttributReadOnly(this Type typeOfObject, string propertyName, bool isReadOnly)
        {
            PropertyDescriptor pd = TypeDescriptor.GetProperties(typeOfObject)[propertyName];
            var att = pd.Attributes[typeof(ReadOnlyAttribute)] as ReadOnlyAttribute;
            if (att != null)
            {
                var fieldDescription = att.GetType().GetField("isReadOnly", BindingFlags.NonPublic | BindingFlags.Instance);
                if (fieldDescription != null)
                {
                    fieldDescription.SetValue(att, isReadOnly);
                }
            }
        }
于 2017-09-08T13:35:49.457 に答える
-9

Java では、マップを使用して独自の Key-Value コーディングを実装することで、これを回避していました。

http://developer.apple.com/documentation/Cocoa/Conceptual/KeyValueCoding/KeyValueCoding.html

于 2008-09-24T19:45:34.760 に答える