Атрибуты .NET: Почему GetCustomAttributes () каждый раз создает новый экземпляр атрибута? - PullRequest
10 голосов
/ 06 января 2009

Поэтому я немного поигрался с атрибутами в .NET и понял, что каждый вызов Type.GetCustomAttributes () создает новый экземпляр моего атрибута. Это почему? Я бы подумал, что экземпляр атрибута в основном будет singleton-per-MemberInfo, с 1 экземпляром, связанным с Type, PropertyInfo и т. Д ...

Вот мой тестовый код:

using System;

namespace AttribTest
{
[AttributeUsage(AttributeTargets.Class)]
class MyAttribAttribute : Attribute
{
    public string Value { get; set; }

    public MyAttribAttribute()
        : base()
    {
        Console.WriteLine("Created MyAttrib instance");
    }
}

[MyAttrib(Value = "SetOnClass")]
class MyClass
{
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Getting attributes for MyClass.");
        object[] a = typeof(MyClass).GetCustomAttributes(false);
        ((MyAttribAttribute)a[0]).Value = "a1";

        Console.WriteLine("Getting attributes for MyClass.");
        a = typeof(MyClass).GetCustomAttributes(false);
        Console.WriteLine(((MyAttribAttribute)a[0]).Value);

        Console.ReadKey();
    }
}
}

Теперь, если бы I должен был реализовать атрибуты, я бы ожидал, что результат будет:

Created MyAttrib instance
Getting attributes for MyClass.
Getting attributes for MyClass.
a1

Где "загрузчик классов" (извините, у меня больше Java-фона, но я не уверен на 100%, как .net загружает его типы) будет компилировать MyClass, создавать экземпляр MyAttribAttribute и хранить их где-нибудь вместе. (вероятно, Perm Gen в куче, если бы это была Java) 2 вызова GetCustomAttributes () просто вернут тот же ранее созданный экземпляр.

Но фактический результат:

Getting attributes for MyClass.
Created MyAttrib instance
Getting attributes for MyClass.
Created MyAttrib instance
SetOnClass

Так ... почему? Кажется, что создание нового экземпляра всех этих объектов для каждого вызова немного чрезмерно и не подходит для управления производительностью / памятью. Есть ли способ всегда получать один и тот же экземпляр снова и снова?

У кого-нибудь есть идеи, почему он был разработан таким образом?

Причина, по которой меня это вообще волнует, заключается в том, что я создал собственный атрибут, который внутренне содержит некоторую информацию о проверке, поэтому в Атрибуте у меня в основном есть «private bool Validated», который я установил в true. Проверка занимает некоторое время, поэтому я не хочу запускать ее каждый раз. Теперь проблема в том, что, поскольку он создает новый экземпляр атрибута каждый раз, когда я получаю атрибуты, Validated всегда имеет значение «false».

Ответы [ 3 ]

11 голосов
/ 06 января 2009

Атрибуты не хранятся в памяти как объекты, они хранятся только в виде метаданных в сборке. Когда вы запросите его, он будет сконструирован и возвращен, и обычно атрибуты являются одноразовыми объектами, поэтому для среды выполнения их нужно хранить на всякий случай, если они вам понадобятся снова, вероятно, будут тратить много памяти.

Короче говоря, вам нужно найти другой способ хранения вашей общей информации.

Вот [MSDN] (http://msdn.microsoft.com/en-us/library/5x6cd29c(VS.71%29.aspx) страница по атрибутам.

10 голосов
/ 06 января 2009

Создание объекта дешево.

Если у вас есть такой атрибут, как

public class MyAttribute : Attribute {
    public virtual string MyText { get; set; }
}

и применил его к классу типа

[MyAttribute(MyText="some text")]
public class MyClass {
}

и вы получили такой, как

var attr =
    typeof(MyClass).GetCustomAttributes(typeof(MyAttribute), false)
    .Cast<MyAttribute>().Single();

и вы устанавливаете некоторые свойства, например

attr.MyText = "not the text we started with";

что должно произойти, и что произойдет , когда вы в следующий раз позвоните

Console.WriteLine(
    typeof(MyClass).GetCustomAttributes(typeof(MyAttribute), false)
    .Cast<MyAttribute>().Single().Name
);

2 голосов
/ 06 января 2009

Это потому, что атрибуты сохраняются в метаданных. Атрибуты должны использоваться для такой информации, как «удобное имя свойства» и т. Д. *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...