Хорошо, я знаю, о чем вы думаете: «Зачем писать метод, который вы не хотите, чтобы люди использовали?» Правильно?
Короче говоря, у меня есть класс, который нужно сериализовать в XML. Чтобы XmlSerializer мог творить чудеса, у класса должен быть пустой конструктор по умолчанию:
public class MyClass
{
public MyClass()
{
// required for xml serialization
}
}
Итак, мне нужно это иметь, но я не хочу, чтобы люди использовать это, поэтому есть ли какой-либо атрибут, который можно использовать, чтобы пометить метод как «НЕ ИСПОЛЬЗОВАТЬ»?
Я думал об использовании атрибута Устаревший (так как это может остановить сборку), но это кажется немного «неправильным», есть ли другой способ сделать это, или мне нужно идти вперед и укусить пулю? :)
Хорошо, я принял ответ Кита, поскольку в глубине души полагаю, что полностью согласен. Вот почему я в первую очередь задал вопрос: мне не нравится идея наличия атрибута Устаревший.
является все еще проблема, хотя мы получаем уведомление в intellisense, в идеале мы хотели бы прервать сборку, так есть ли способ сделать это? Возможно, создать собственный атрибут?
Создан более конкретный вопрос здесь.





Прочитал заголовок и сразу подумал «устаревший атрибут». Как насчет
/// <summary>
/// do not use
/// </summary>
/// <param name = "item">don't pass it anything -- you shouldn't use it.</param>
/// <returns>nothing - you shouldn't use it</returns>
public bool Include(T item) {
....
ObsoleteAttribute, вероятно, будет работать в вашей ситуации - вы даже можете вызвать сбой сборки, если использовать этот метод.
Поскольку устаревшие предупреждения возникают во время компиляции и поскольку отражение, необходимое для сериализации, происходит во время выполнения, отметка этого метода как устаревшего не нарушит сериализацию, но предупредит разработчиков, что метод не существует для использования.
Вы ищете класс ObsoleteAttribute:
using System;
public sealed class App {
static void Main() {
// The line below causes the compiler to issue a warning:
// 'App.SomeDeprecatedMethod()' is obsolete: 'Do not call this method.'
SomeDeprecatedMethod();
}
// The method below is marked with the ObsoleteAttribute.
// Any code that attempts to call this method will get a warning.
[Obsolete("Do not call this method.")]
private static void SomeDeprecatedMethod() { }
}
Я не согласен с использованием Obsolete, поскольку это обычно означает «будет удалено в более позднем выпуске ..»
Да, есть.
Я написал об этом в блоге Работа с дизайнером.
А вот код:
public class MyClass
{
[Obsolete("reason", true)]
public MyClass()
{
// required for xml serialization
}
}
Я просто перешел по вашей ссылке (всего через шесть лет после того, как вы ее разместили), и она мертва.
Вау, эта проблема меня тоже беспокоит.
Вам также нужны конструкторы по умолчанию для NHibernate, но я хочу заставить людей НЕ использовать инициализаторы объектов C# 3.0, чтобы классы проходили через код конструктора.
Если класс - [Serialisable] (т.е. он может быть скопирован в любое место по мере необходимости), для десериализации необходим конструктор без параметров.
Я предполагаю, что вы хотите, чтобы доступ вашего кода передавал значения по умолчанию для ваших свойств параметризованному конструктору.
По сути, вы говорите, что XmlSerializer может сделать копию, а затем установить свойства, но вы не хотите, чтобы это делал ваш собственный код.
В некоторой степени я думаю, что это чрезмерный дизайн.
Просто добавьте XML-комментарии, подробно описывающие, какие свойства нужно инициализировать (и что именно).
Не используйте [Obsolete], потому что это не так. Зарезервируйте это для действительно устаревших методов.
Может потребоваться конструктор без параметров, но (де) сериализаторы не должны требовать, чтобы он был общедоступным.
На самом деле я был бы склонен не согласиться со всеми, кто выступает за использование ObsoleteAttribute, поскольку в документации MSDN говорится, что:
Marking an element as obsolete informs the users that the element will be removed in future versions of the product.
Поскольку универсальные конструкторы для сериализации XML не следует удалять из приложения, я бы не стал применять их на всякий случай, если разработчик обслуживания в будущем не знаком с тем, как работает сериализация XML.
На самом деле я использовал метод Кита, просто отмечая, что конструктор используется для сериализации в документации XML, чтобы он отображался в Intellisense.
Вы можете использовать:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
чтобы он не отображался в Intellisence. Если потребитель все еще хочет использовать его, он может, но он не будет таким заметным.
Тем не менее, точка зрения Кейтса о инженерии остается в силе.
Это больше не работает с 2013 года: github.com/dotnet/roslyn/issues/37478
Вы можете создать свой собственный производный класс Attribute, скажем NonCallableAttribute, чтобы квалифицировать методы, а затем добавить к своей задаче анализа кода сборки / CI проверку, чтобы отслеживать, использует ли какой-либо код эти методы.
На мой взгляд, вы действительно не можете заставить разработчиков не использовать этот метод, но вы можете как можно скорее обнаружить, когда кто-то нарушил правило, и исправить это.
Знаете ли вы, как, как только мы создадим этот атрибут, вы скажете, как? не знаю ... пометить метод линией запаса? вроде того, что делают устаревшие, но я не хочу отказывать пользователю, просто хочу сказать ему, что есть лучший вариант, который также соблюдает это свойство ...
@deadManN До VS2015, насколько мне известно, не было простого способа имитировать предупреждение, которое Visual Studio показывает для атрибута Obsolete для других настраиваемых атрибутов. Вот почему я предложил провести некоторый анализ во время сборки с помощью специального сценария MSBuild или любой другой программы, которая может загружать ваши сборки и выполнять анализ на основе отражения. НО специально для Visual Studio 2015 и далее вы можете захотеть изучить новую технологию Roslyn Live Analyzers, которая позволяет вам делать именно это: msdn.microsoft.com/en-us/magazine/dn879356.aspx
о, спасибо, ну я использую 2015, кстати, я хочу знать, что бы вы сделали, чтобы сказать VS, чтобы предупредить людей? и я не уверен, слышал ли я раньше слово CI, что это ... и как добавить задачу анализа и на что она способна ... (если вы можете объяснить, я буду благодарен)
throw new ISaidDoNotUseException();
Я разрываюсь между голосованием "против", потому что это сломает десериализатор, и голосованием "за" из-за того, как много я смеялся ...
Я тоже засмеялся! Смешно: D
Отделите сериализуемый объект от объекта домена.
Проголосовали за, потому что это правильный способ решения проблемы, но это головная боль.
Хороших ответов уже достаточно много. Но я думаю, что лучший вариант - использовать сериализатор, который может использовать параметризованный конструктор. Вам не нужен сериализатор, но, например, Entity Framework Core знает, как использовать параметризованные конструкторы.
Документация Entity Framework Core:
If EF Core finds a parameterized constructor with parameter names and types that match those of mapped properties, then it will instead call the parameterized constructor with values for those properties and will not set each property explicitly.
Я собирался создать свой собственный
WarnOnUseAttribute, производный отObsoleteAttribute, чтобы указать, что метод не должен вызываться, даже если он не является «устаревшим» (например, я написал метод расширенияBuffered(), который обновляетIEnumerable<T>доIReadOnlyList<T>, и этот метод бесполезен, если аргумент уже имеет типIReadOnlyList<T>, поэтому я создаю специальную перегрузку с[WarnOnUse("...")], которая принимаетIReadOnlyList<T>). Это не сработало, потому чтоObsoleteAttribute- этоsealed.