Получить атрибут для класса, содержащего свойство с инициализацией Lazy - PullRequest
0 голосов
/ 19 июня 2019

Я не думаю, что то, что я пытаюсь сделать, возможно. У меня есть свойство, которое инициализируется ленивым. В конструкторе я хочу получить значение атрибута в классе, который содержит свойство. У меня есть минимальный пример ниже.

public class Demo
{
    private Lazy<InternalDemo> data;

    public Demo(*stuff*)
    {
        data = new Lazy<InternalDemo>(*stuff*);
    }

    public string GetDetails()
    {
        return data.Value.Details;
    }

    private class InternalDemo
    {
        public string Details { get; set; }
        public InternalDemo()
        {
            //Details = SomeAttribute.Text
        }
    }
}

[SomeAttribute("Here are details")]
public static class DemoContainer
{
    public static Demo Things { get; } = new Demo();
}

[SomeAttribute("Here are more details")]
public static class DemoContainer2
{
    public static Demo2 Things { get; } = new Demo();
}

//Value is referenced via 
DemoContainer.Demo.GetDetails() //"Here are details"
DemoContainer2.Demo2.GetDetails() //"Here are more details"
//etc

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

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

Я знаю, что мог передать тип DemoContainer или значение SomeAttribute конструктору Demo, но цель этого атрибута состояла в том, чтобы избежать необходимости делать это. Свойства являются статическими, потому что они являются частью механизма кэширования, но я не хотел их инициализировать, пока они не будут фактически использованы.

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

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

1 Ответ

0 голосов
/ 19 июня 2019

Когда вы вызываете DemoContainer.Demo, он возвращает экземпляр Demo, который не «знает», откуда он взялся.Ничто не ссылается на класс DemoContainer, что означает, что вы не можете получить доступ к атрибуту этого класса.

Хотя экземпляр Demo не знает, откуда он, вы знаете, откуда он пришелпотому что ты это называешь.Таким образом, в любой момент, когда вы вызываете DemoContainer.Demo, вы также можете прочитать атрибут из DemoContainer:

var someAttribute = typeof(DemoContainer).GetCustomAttribute(typeof(SomeAttributeAttribute))
    as SomeAttributeAttribute;
var attributeValue = someAttribute?.AttributeValue;

Но если вы захотите использовать это значение, это будет намного проще:

public static class DemoContainer
{
    public const string Details = "Here are details";
    public static Demo Things { get; } = new Demo();
}

Другими словами, зачем вообще читать его из атрибута?

Но даже лучше, если вы хотите, чтобы создатель объекта каким-то образом включал информацию в объект, выможно просто сделать это через конструктор объекта.

public static class DemoContainer
{
    public static Demo Things { get; } = new Demo("Here are details");
}

Это кажется наиболее интуитивным способом получить желаемый результат.

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