Pergunta

Ao usar o ObsoleteAtribute na Net dá-lhe avisos do compilador dizendo-lhe que o objeto / método / propriedade é obsoleta e somthing mais deve ser usado. Atualmente estou trabalhando em um projeto que requer uma grande quantidade de refatoração um código de ex-funcionários. Eu quero escrever um atributo personalizado que eu possa usar para métodos marca ou propriedades que irão gerar avisos do compilador que dão mensagens que eu escrevo. Algo como isto

[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

Eu quero isso para gerar um aviso do compilador que diz: "Esta é uma droga de código e deve ser olhado". Eu sei como criar um atributo personalizado, a questão é como faço para causar-lo para gerar avisos do compilador no estúdio visual.

Foi útil?

Solução

Atualização

Esta é agora possível com Roslyn (Visual Studio 2015). Você pode construção um código analisador para verificar se há um atributo personalizado


Eu não acredito que é possível. ObsoleteAttribute é tratado especialmente pelo compilador e é definido na norma C #. Por que na terra é ObsoleteAttribute não é aceitável? Parece-me que esta é precisamente a situação que foi projetado para, e atinge exatamente o que você precisar!

Observe também que Visual Studio pega os avisos gerados por ObsoleteAttribute on the fly também, o que é muito útil.

Não quero ser inútil, me perguntando por que você não está interessado em usá-lo ...

Infelizmente ObsoleteAttribute é selada (provavelmente em parte devido ao tratamento especial), portanto, você não pode subclasse seu próprio atributo da mesma.

A partir do padrão C #: -

O atributo obsoleto é usado para marcar tipos e membros de tipos que deve deixará de ser utilizado.

Se um programa usa um tipo ou membro que é decorado com o Obsoleto atributo, o compilador emite um aviso ou um erro. Especificamente, o questões compilador um aviso se nenhum erro parâmetro é fornecido, ou se o erro parâmetro é fornecido e tem a valor falso. A um questões compilador erro se o parâmetro de erro é especificada e tem o valor verdadeiro.

Não que soma-se às suas necessidades? ... você não vai fazer melhor do que isso eu não acho.

Outras dicas

Não sei se isso vai funcionar, mas vale a pena uma tentativa.

Você não pode estender Obsoleto, porque o seu final, mas talvez você pode criar seu próprio atributo, e marcar essa classe como obsoletos como esta:

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

Então, quando você marcar seus métodos com o atributo "MustRefactor", os avisos de compilação pode mostrar.

Eu disse "talvez" e "poder", porque eu não tentei isso. Por favor, me diga se ele não funcionar, então eu vou remover a resposta.

Saudações!

UPDATE: Testado ele. Ele gera um aviso de tempo de compilação, mas a mensagem de erro parece engraçado, você deve ver por si mesmo e escolha. Isto é muito próximo ao que você queria alcançar.

UPDATE2: Com este código Ele gera estes avisos (não muito agradável, mas eu não acho que há algo melhor).

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
{

}

Em alguns compiladores você pode usar #WARNING para emitir um aviso:

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

compiladores Na Microsoft, normalmente você pode usar o pragma mensagem:

#pragma message ( "text" )

Você mencionou .Net, mas não especificou se você estava programação com C / C ++ ou C #. Se você está programando em C #, que você deve saber que C # suporta o formato #warning .

No momento, estamos no meio de um monte de refatoração onde não podíamos consertar tudo imediatamente. Nós só usar o comando #warning preproc onde precisamos voltar e olhar no código. Mostra-se na saída do compilador. Eu não acho que você pode colocá-lo em um método, mas você pode colocá-lo apenas dentro do método, e ainda é fácil de encontrar.

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

No VS 2008 (+ SP1) #warnings não mostrar corretamente na lista de erro após Limpo soultion & Reconstruir solução, não todos eles. Alguns avisos são mostrados na lista de erros só depois de eu abrir determinado arquivo de classe. Então, eu fui forçado a atributo de uso personalizado:

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

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

    public MappingToDo()
    {}
}

Então, quando eu sinalizar algum código com ele

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

Ela produz advertências como esta:

Namespace.MappingToDo é obsoleto: 'Mapeamento todo'.

Eu não posso mudar o texto da advertência, 'Some comentário' não é o mostrou Erro Lista. Mas vai saltar para local adequado no arquivo. Então, se você precisa variar essas mensagens de aviso, criar vários atributos.

O que você está tentando fazer é um desvio de atributos. Em vez disso usar a lista de tarefas do Visual Studio. Você pode inserir um comentário em seu código como este:

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

Então Ver abrir / lista de tarefas a partir do menu. A lista de tarefas tem duas categorias, tarefas de usuário e comentários. Mudar para comentários e você verá todos os seus // Todo: 's lá. Clicando duas vezes em um TODO irá saltar para o comentário em seu código.

Al

Eu não acho que você pode. Tanto quanto eu sei suporte para ObsoleteAttribute é essencialmente codificado no compilador C #; você não pode fazer algo semelhante diretamente.

O que você pode ser capaz de fazer é usar uma tarefa MSBuild (ou um evento pós-compilação) que executa uma ferramenta personalizada contra o recém-compilados montagem. A ferramenta personalizada iria reflectir sobre todos os tipos / métodos na montagem e consumir o seu atributo personalizado, em que ponto ele pode imprimir em TextWriters padrão ou erro de System.Console.

Olhando para a fonte para ObsoleteAttribute , ele doesn 't olhar como ele está fazendo nada de especial para gerar um aviso do compilador, então eu tendem a ir com @ technophile e dizer que é embutida no compilador. Existe uma razão que você não quer usar apenas ObsoleteAttribute para gerar suas mensagens de aviso?

Há vários comentários que sugerem para inserir avisos ou pragma. trabalhos obsoletos de uma forma muito diferente! Marcação função de um obsoleto de um L biblioteca, a mensagem obsoleto levanta quando um programa chama a função mesmo que o programa chamador não está na biblioteca L. Aviso aumenta a mensagem somente quando L é compilado.

Aqui está a Implementação Roslyn, assim você pode criar seus próprios atributos que dão avisos ou erros na mosca.

Eu tenho criar um tipo de atributo IdeMessage Chamado que será o atributo que gera avisos:

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

    public IDEMessageAttribute(string message);
}

Para fazer isso, você precisa instalar o Roslyn SDK primeira e iniciar um novo projeto VSIX com analisador. Omiti algumas das peças menos importantes, como as mensagens, você pode descobrir como fazer isso. Em seu analisador você fizer isso

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);
}

Não há CodeFixProvider para isso você pode removê-lo a partir da solução.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top