Автоматическая генерация неизменного класса и соответствие классу разработчика

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

Пример ввел:

struct Foo
{
    public int apples;
    public int oranges;
    public Foo Clone() {return (Foo) base.MemberwiseClone();}
}

Пример произвел:

public class ImmutableFoo // could probably be a struct
{
    private Foo snapshot;
    internal ImmutableFoo(Foo value) { this.snapshot = value; }
    public FooBuilder Builder() { return new FooBuilder(snapshot); }
    public int Apples { get { return snapshot.apples; } }
    public int Oranges { get { return snapshot.oranges; } }
}

public class FooBuilder
{
    private Foo state;

    public int Apples { get { return state.apples; } set { state.apples = value; } }
    public int Oranges { get { return state.oranges; } set { state.oranges = value; } }

    public FooBuilder() { }

    internal FooBuilder(Foo toCopy) { state = toCopy.Clone(); }

    public ImmutableFoo Build()
    {
        ImmutableFoo result = new ImmutableFoo(state);
        state = state.Clone();
        return result;
    }
}

Такой "инструмент" мог быть плагином IDE или мог генерировать новый класс во времени выполнения с помощью отражения.

Пример находится в C#, но я интересовался бы решением для любого языка OO со статическим контролем типов (Java, Scala, C++ и т.д.)

Желательные функции:

  • Воссоздает методы от структуры в классе разработчика
  • Воссоздает неразрушающие методы от структуры в неизменном классе (особенно. Equals() и GetHashCode() и любые методы интерфейса)
  • Также генерирует a IFooReader интерфейс, содержащий свойства только для чтения для каждого участника структуры, реализованного и неизменным и разработчиком.
  • Если класс поля имеет неизменный эквивалент, использует неизменную версию в неизменном классе (см. также, Как я создаю разработчика в C# для объекта, который имеет свойства, которые являются типами referenc?), например. List -> ReadOnlyCollection или подобный.
  • Кроме того, посещайте урок разработчика, как введено (где разработчик использует автоматические свойства вместо того, чтобы делегировать к структуре.)
  • Не требует Clone метод, который будет предопределен

"Вы не должны использовать инструмент как это, потому что..." ответы также приветствуются.

12
задан Community 23 May 2017 в 12:34
поделиться

2 ответа

Вот четыре возможных решения.

1) Используйте CodeDOM для генерации кода на C# или VB. Это также позволит вам использовать расширения visual studio для генерации кода в файлах дизайнера. Аналогично некоторым встроенным инструментам, которые уже предлагает visual studio - например, тем, которые генерируют обертки для вызовов веб-сервисов и т.д. К сожалению, я не очень много знаю о расширении Visual Studio.

  • Плюсы - Вы можете генерировать исходники до сборки. Это облегчает написание кода против сгенерированных типов из любой сборки.
  • Минусы - Не является языковым агностиком. Вы застряли с теми языками, которые поддерживаются.

2) Используйте библиотеку Mono.Cecil для анализа вашей сборки после сборки. Затем вы можете переписать сборку с включением новых типов.

  • Плюсы - Независимость от языка.
  • Минусы - Если вы добавите типы в ту же сборку, в которой определены ваши структуры, вы не сможете писать код против сгенерированных неизменяемых типов структур в той же сборке. Если вы поместите сгенерированные типы в новую сборку, то это возможно.

3) Использовать PostSharp. Я не так много знаю об этой библиотеке, поэтому, возможно, вы не сможете добавить новые типы в вашу сборку, но я знаю, что вы можете внедрять IL в методы. В ней также есть много хороших вещей, которые позволяют легко делать это с помощью атрибутов. Таким образом, вы можете сделать следующее -

[GenerateImmutable]
struct Foo
{
    public int apples;
    public int oranges;
    public Foo Clone() {return (Foo) base.MemberwiseClone();}
}
  • Плюсы - не зависит от языка, AOP легче сделать в PostSharp.
  • Минусы - То же самое, что и с Mono.Cecil, а также не уверен, что вы можете генерировать новые типы с помощью PostSharp.

4) Используйте встроенные библиотеки Reflection.Emit для генерации новой сборки с неизменяемыми типами.

  • Плюсы - Независимость от языка, отсутствие сторонних вещей.
  • Минусы - Нужно помещать сгенерированные типы в новые сборки. Нельзя добавить их в ту же сборку, в которой находится исходный тип.
4
ответ дан 2 December 2019 в 23:19
поделиться

Предполагая, что вы говорите о контейнере сервлета, обработка сеанса возвращается. См. в соответствующей части руководства по JavaEE . Он охватывает API сеанса, а также то, как отслеживаются сеансы (перезапись файлов cookie или URL).

-121--4817553-

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

FOR /r %%X IN (*.txt) DO (
    ECHO %%X
    DEL %%X
)

Размещение ( и ) имеет значение. Круглые скобки после DO должны быть помещены в ту же строку, в противном случае пакетный файл будет неправильным.

Подробнее см. , если/? | найти/V «» .

-121--702479-

Зачем беспокоиться о построителе?

У вас есть (противная) изменяемая структура, но если вы должны использовать ее напрямую, а не создавать громоздкий и ненужный Builder.

Меня несколько беспокоит, что у вас есть достаточное количество этих структур, чтобы вы почувствовали, что вам нужно автоматически генерировать обертки такого рода. Моя кишечная реакция в том, что ты делаешь это неправильно...

Если целью неизменяемой оболочки является просто хранение снимка, то просто используйте что-то подобное:

public struct Snapshot<T> where t : struct
{
    private readonly T data;
    public Snapshot(T value) { this.data = value; }
    public T Data { get { return data; } }
}

Переданная структура гарантированно больше никогда не изменится, но вы можете получить доступ ко всем значениям на ней напрямую (и изменения этих результатов происходят на копии, созданной при вызове базовой функции get_Data)

2
ответ дан 2 December 2019 в 23:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: