Вопрос

При использовании ObsoleteАтрибута в .Net он выдает вам предупреждения компилятора о том, что объект / метод / свойство устарели и следует использовать что-то еще.В настоящее время я работаю над проектом, который требует большого рефакторинга кода бывших сотрудников.Я хочу написать пользовательский атрибут, который я могу использовать для обозначения методов или свойств, которые будут генерировать предупреждения компилятора, выдающие сообщения, которые я пишу.Что - то вроде этого

[MyAttribute("This code sux and should be looked at")]
public void DoEverything()
{
}
<MyAttribute("This code sux and should be looked at")>
Public Sub DoEverything()
End Sub

Я хочу, чтобы это сгенерировало предупреждение компилятора, в котором говорится: "Этот код sux и его следует просмотреть".Я знаю, как создать пользовательский атрибут, вопрос в том, как мне заставить его генерировать предупреждения компилятора в Visual Studio.

Это было полезно?

Решение

Обновить

Теперь это возможно с помощью Roslyn (Visual Studio 2015).Ты можешь строить a анализатор кода чтобы проверить наличие пользовательского атрибута


Я не верю, что это возможно.ObsoleteAttribute обрабатывается компилятором особым образом и определен в стандарте C #.С какой стати устаревший атрибут является неприемлемым?Мне кажется, что это именно та ситуация, для которой он был разработан, и он достигает именно того, что вам нужно!

Также обратите внимание, что Visual Studio также "на лету" распознает предупреждения, сгенерированные ObsoleteAttribute, что очень полезно.

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

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

Из стандарта C #:-

Атрибут Устаревший используется для обозначения типов и членов типов, которые больше не должны использоваться.

Если программа использует тип или элемент , который оформлен атрибутом Устаревший , компилятор выдает предупреждение или ошибку.В частности, компилятор выдает предупреждение, если параметр error не указан или если параметр error предоставлен и имеет значение false.Компилятор выдает сообщение об ошибке , если параметр error указан и имеет значение true.

Разве это не подводит итог вашим потребностям?...не думаю, что ты добьешься большего, чем это.

Другие советы

Не знаю, сработает ли это, но попробовать стоит.

Вы не можете расширить устаревший класс, потому что он окончательный, но, возможно, вы можете создать свой собственный атрибут и пометить этот класс как устаревший следующим образом:

[Obsolete("Should be refactored")]
public class MustRefactor: System.Attribute{}

Затем, когда вы помечаете свои методы атрибутом "MustRefactor", могут отображаться предупреждения о компиляции.

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

С уважением!

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

ОБНОВЛЕНИЕ 2:С этот код Это порождает это предупреждение (не очень приятно, но я не думаю, что есть что-то лучше).

public class User
{
    private String userName;

    [TooManyArgs] // Will show warning: Try removing some arguments
    public User(String userName)
    {
        this.userName = userName;   
    }

    public String UserName
    {
        get { return userName; }
    }
    [MustRefactor] // will show warning: Refactor is needed Here
    public override string ToString()
    {
        return "User: " + userName;
    }
}
[Obsolete("Refactor is needed Here")]
public class MustRefactor : System.Attribute
{

}
[Obsolete("Try removing some arguments")]
public class TooManyArgs : System.Attribute
{

}

В некоторых компиляторах вы можете использовать #warning для выдачи предупреждения:

#warning "Do not use ABC, which is deprecated. Use XYZ instead."

В компиляторах Microsoft обычно можно использовать прагму message:

#pragma message ( "text" )

Вы упомянули .Net, но не уточнили, программируете ли вы на C / C ++ или C #.Если вы программируете на C #, то вам следует знать, что C # поддерживает формат #warning.

В настоящее время мы находимся в процессе большого рефакторинга, где мы не смогли исправить все сразу.Мы просто используем команду #warning preproc, где нам нужно вернуться назад и посмотреть на код.Это отображается в выходных данных компилятора.Я не думаю, что вы можете поместить это в метод, но вы могли бы поместить это просто внутри метода, и его все равно легко найти.

public void DoEverything() {
   #warning "This code sucks"
}

В VS 2008 (+ sp1) # предупреждения не отображаются должным образом в списке ошибок после очистки Soultion & Rebuild Solution, не все из них.Некоторые предупреждения отображаются в списке ошибок только после того, как я открываю определенный файл класса.Поэтому я был вынужден использовать пользовательский атрибут:

[Obsolete("Mapping ToDo")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)]
public class MappingToDo : System.Attribute
{
    public string Comment = "";

    public MappingToDo(string comment)
    {
        Comment = comment;
    }

    public MappingToDo()
    {}
}

Поэтому, когда я помечаю им какой-то код

[MappingToDo("Some comment")]
public class MembershipHour : Entity
{
    // .....
}

Он выдает предупреждения, подобные этому:

Пространство имен.MappingToDo устарел:"Сопоставление задач".

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

То, что вы пытаетесь сделать, - это неправильное использование атрибутов.Вместо этого используйте список задач Visual Studio.Вы можете ввести комментарий в свой код следующим образом:

//TODO:  This code sux and should be looked at
public class SuckyClass(){
  //TODO:  Do something really sucky here!
}

Затем откройте Вид / Список задач из меню.Список задач состоит из двух категорий: пользовательские задачи и Комментарии.Переключитесь на Комментарии, и вы увидите там все ваши //Todo:.Двойной щелчок по задаче приведет к переходу к комментарию в вашем коде.

Эл

Я не думаю, что ты сможешь.Насколько я знаю, поддержка ObsoleteAttribute, по сути, жестко запрограммирована в компиляторе C #;вы не можете сделать ничего подобного напрямую.

Что вы могли бы сделать, так это использовать задачу MSBuild (или событие после сборки), которое запускает пользовательский инструмент для только что скомпилированной сборки.Пользовательский инструмент будет отражать все типы / методы в сборке и использовать ваш пользовательский атрибут, после чего он сможет печатать в системе.Средства ввода текста консоли по умолчанию или с ошибкой.

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

Есть несколько комментариев, в которых предлагается вставить предупреждения или прагму.Устаревшее работает совсем по-другому!Помечая функцию библиотеки L устаревшей, при вызове программы появляется сообщение устаревшая, даже если вызывающая программа отсутствует в библиотеке L.Предупреждение выдает сообщение ТОЛЬКО тогда, когда L скомпилирован.

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

Я создал тип атрибута Под названием IdeMessage который будет атрибутом, генерирующим предупреждения:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class IDEMessageAttribute : Attribute
{
    public string Message;

    public IDEMessageAttribute(string message);
}

Для того, чтобы сделать это, вам необходимо сначала установить Roslyn SDK и запустить новый проект VSIX с помощью analyzer.Я опустил некоторые менее релевантные фрагменты, такие как сообщения, вы можете понять, как это сделать.В своем анализаторе вы делаете это

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxNodeAction(AnalyzerInvocation, SyntaxKind.InvocationExpression);
}

private static void AnalyzerInvocation(SyntaxNodeAnalysisContext context)
{
    var invocation = (InvocationExpressionSyntax)context.Node;

    var methodDeclaration = (context.SemanticModel.GetSymbolInfo(invocation, context.CancellationToken).Symbol as IMethodSymbol);

    //There are several reason why this may be null e.g invoking a delegate
    if (null == methodDeclaration)
    {
        return;
    }

    var methodAttributes = methodDeclaration.GetAttributes();
    var attributeData = methodAttributes.FirstOrDefault(attr => IsIDEMessageAttribute(context.SemanticModel, attr, typeof(IDEMessageAttribute)));
    if(null == attributeData)
    {
        return;
    }

    var message = GetMessage(attributeData); 
    var diagnostic = Diagnostic.Create(Rule, invocation.GetLocation(), methodDeclaration.Name, message);
    context.ReportDiagnostic(diagnostic);
}

static bool IsIDEMessageAttribute(SemanticModel semanticModel, AttributeData attribute, Type desiredAttributeType)
{
    var desiredTypeNamedSymbol = semanticModel.Compilation.GetTypeByMetadataName(desiredAttributeType.FullName);

    var result = attribute.AttributeClass.Equals(desiredTypeNamedSymbol);
    return result;
}

static string GetMessage(AttributeData attribute)
{
    if (attribute.ConstructorArguments.Length < 1)
    {
        return "This method is obsolete";
    }

    return (attribute.ConstructorArguments[0].Value as string);
}

Для этого нет CodeFixProvider, вы можете удалить его из решения.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top