Как использовать отражение для упрощения конструкторов и сравнений?

В C# самое близкое к специализации должно использовать более - определенная перегрузка; однако, это является хрупким, и не покрывает каждое возможное использование. Например:

void Foo<T>(T value) {Console.WriteLine("General method");}
void Foo(Bar value) {Console.WriteLine("Specialized method");}

Здесь, если компилятор знает типы в компиляции, он выберет самое определенное:

Bar bar = new Bar();
Foo(bar); // uses the specialized method

Однако....

void Test<TSomething>(TSomething value) {
    Foo(value);
}

будет использовать Foo<T> даже для TSomething=Bar, поскольку это записывается в во время компиляции.

Еще один подход должен использовать сертификационное испытание в общий метод - однако, это обычно - плохая идея и не рекомендуется.

В основном, C# просто не хочет, чтобы Вы работали со специализациями, за исключением полиморфизма:

class SomeBase { public virtual void Foo() {...}}
class Bar : SomeBase { public override void Foo() {...}}

Здесь Bar.Foo будет всегда решать к корректному переопределению.

12
задан Mogsdad 27 September 2015 в 02:24
поделиться

4 ответа

Следующий раздел книги, One Level of Абстракция на функцию имеет большое значение для ответа на этот вопрос. Все эти операторы находятся на одном уровне абстракции, поэтому эта функция уже выполняет одно действие, сохраняя настройки.

public Foo(IFoo other) {
    foreach (var property in MyCacheProvider.GetProperties<IFoo>())
        property.SetValue(this, property.GetValue(other, null), null);
}
5
ответ дан 2 December 2019 в 21:44
поделиться

ИМХО, отражение - очень мощная функция C #, но она с большой вероятностью приведет к раздутому коду, что значительно увеличивает время обучения кода и снижает ремонтопригодность. Вы с большей вероятностью совершите ошибки (как только базовый рефакторинг может привести к ошибкам) ​​и будете больше бояться изменить имя любого свойства (если вы найдете имя получше) или тому подобное.

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

2
ответ дан 2 December 2019 в 21:44
поделиться

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

Библиотека называется AutoMapper и отображает один объект в другой, динамически создавая сборку IL на лету. Это гарантирует, что кроме первого попадания вы получите превосходную производительность, а ваш код будет намного проще:

public Foo(Foo other)
{
    Mapper.Map(other, this);
}

Это имеет тенденцию отлично работать и имеет дополнительный бонус в виде того, что здесь не изобретено, что я поклонник.

Я провел несколько тестов производительности, и после первых 20 мсек (все еще довольно быстро) она была настолько близка к 0, насколько это возможно. Впечатляет.

Надеюсь, это кому-то поможет.

3
ответ дан 2 December 2019 в 21:44
поделиться

Основная проблема заключается в том, что вы пытаетесь использовать статически типизированный язык, например, динамически типизированный.

На самом деле его нет. потребность в чем-нибудь необычном. Если вы хотите иметь возможность перебирать свойства, вы можете использовать Map <> в качестве резервного хранилища для всех свойств в вашем классе.

По совпадению, именно так мастер проекта VS применяет для вас настройки приложения. (см. System.Configuration.ApplicationSettingsBase) Это также очень похоже на lua

   public bool ConfirmSync {
        get {
            return ((bool)(this["ConfirmSync"]));
        }
        set {
            this["ConfirmSync"] = value;
        }
    }
2
ответ дан 2 December 2019 в 21:44
поделиться
Другие вопросы по тегам:

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