在.Net中使用ObsoleteAtribute时,它会为您提供编译器警告,告诉您对象/方法/属性已过时,应该使用其他东西。我目前正在开发一个需要大量重构前雇员代码的项目。我想编写一个自定义属性,我可以用它来标记将生成编译器警告的方法或属性,这些警告会给出我写的消息。像这样的东西

[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)。您可以构建 代码分析器检查自定义属性


我不相信这是可能的。 ObsoleteAttribute由编译器专门处理,并在C#标准中定义。为什么ObsoleteAttribute不被接受?在我看来,这正是它所针对的情况,并准确地实现了您的需求!

另请注意,Visual Studio也会即时获取由ObsoleteAttribute生成的警告,这非常有用。

不要故意无益,只是想知道你为什么不热衷于使用它......

不幸的是,ObsoleteAttribute是密封的(可能部分是由于特殊处理),因此您无法从中继承自己的属性。

来自C#标准: -

  

属性Obsolete用于标记   类型和应该类型的成员   不再使用。

     

如果程序使用类型或成员   用过时装饰的   属性,编译器发出一个   警告或错误。具体来说,   如果没有错误,编译器会发出警告   提供参数,或者如果错误   参数提供并具有   价值假。编译器发出一个   错误参数是错误   指定并且值为true。

这不能总结你的需求吗?......你不会做得比我想的更好。

其他提示

不知道这是否有效,但值得一试。

你不能扩展Obsolete,因为它是最终的,但也许你可以创建自己的属性,并将该类标记为过时,如下所示:

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

然后当您使用“MustRefactor”标记您的方法时属性,编译警告可能会显示。

我说“也许”和“可能”因为我没试过这个请告诉我,如果它不起作用,我会删除答案。

问候!

更新:测试过它。它会生成编译时警告,但错误消息看起来很有趣,您应该亲眼看到并选择。这非常接近您想要实现的目标。

<强> UPDATE2: 使用此代码它会生成这个警告(不是很好,但我认为没有更好的东西)。

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编译器中,您通常可以使用消息pragma:

#pragma message ( "text" )

你提到过.Net,但没有说明你是用C / C ++还是用C#编程。如果您使用C#进行编程,那么您应该知道 C#支持#warning格式

我们目前正处于大量重构的中间,我们无法立即解决所有问题。我们只需使用#warning preproc命令,我们需要返回并查看代码。它出现在编译器输出中。我不认为你可以把它放在一个方法上,但你可以把它放在方法中,而且它仍然很容易找到。

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

在VS 2008(+ sp1)中#warnings在Clean Soultion&amp;之后的错误列表中无法正确显示重建解决方案,不是全部。 仅在打开特定类文件后,错误列表中会显示一些警告。 所以我被迫使用自定义属性:

[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
{
    // .....
}

它会产生如下警告:

  

Namespace.MappingToDo已过时:   '映射待办事项'。

我无法更改警告文本,“有些评论”未显示错误列表。 但它会跳到文件中的适当位置。 因此,如果您需要更改此类警告消息,请创建各种属性。

您要做的是滥用属性。而是使用Visual Studio任务列表。您可以在代码中输入注释,如下所示:

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

然后从菜单中打开“查看/任务列表”。任务列表有两个类别,用户任务和注释。切换到评论,你会看到你的所有// Todo:那里。双击TODO将跳转到代码中的注释。

的Al

我认为你不能。据我所知,对ObsoleteAttribute的支持本质上是硬编码到C#编译器中;你不能直接做任何类似的事。

您可以做的是使用MSBuild任务(或构建后事件)对正常编译的程序集执行自定义工具。自定义工具将反映程序集中的所有类型/方法并使用您的自定义属性,此时它可以打印到System.Console的默认值或错误TextWriters。

查看 ObsoleteAttribute 的来源,它没有看起来它正在做一些特殊的事情来生成编译器警告,所以我倾向于使用@ technophile 并说它被硬编码到编译器中。您是否有理由不想使用 ObsoleteAttribute 生成警告信息?

有几条评论建议插入警告或编译指示。 过时的工作方式非常不同! 将库L的函数标记为过时,即使调用者程序不在库L中,当程序调用函数时,过时的消息也会引发。警告仅在编译L时才会引发消息。

这是Roslyn实现,因此您可以创建自己的属性,即时提供警告或错误。

我创建了一个属性Type Called IdeMessage ,它将是生成警告的属性:

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

    public IDEMessageAttribute(string message);
}

为了做到这一点,您需要先安装Roslyn SDK并使用分析器启动一个新的VSIX项目。我省略了一些与消息不太相关的部分,你可以弄清楚如何做到这一点。在您的分析仪中,您可以这样做

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