如何使用.net编译器API检查IDataReader是否关闭

问题描述 投票:1回答:1

我正在尝试编写代码分析器,以检查是否有未关闭的IDataReader。

我已经阅读了this question,但没有解释如何完成,我还尝试通读了github链接中的文档。此处使用的英语太复杂,我不明白我该怎么做。将能够找到所有类型为IDataReader的实例,并在该类型的任何变量超出范围之前验证在其上调用close()方法。

[我试图在Visual Studio中创建一个具有代码修复功能的Analyzer类型的项目,我试图在我的类的Initialize方法中注册操作上下文(从DiagnosticAnalyzer类型扩展如下:

 [DiagnosticAnalyzer(LanguageNames.CSharp)]
public class DataReaderAnalyzerAnalyzer : DiagnosticAnalyzer
{
    public const string DiagnosticId = "DataReaderAnalyzer";

    private static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.AnalyzerTitle), Resources.ResourceManager, typeof(Resources));
    private static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.AnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources));
    private static readonly LocalizableString Description = new LocalizableResourceString(nameof(Resources.AnalyzerDescription), Resources.ResourceManager, typeof(Resources));
    private const string Category = "DBConnectionCheck";

    private static DiagnosticDescriptor Rule = new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: Description);

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } }

    public override void Initialize(AnalysisContext context)
    {

        context.RegisterOperationAction((operationContext) => 
        {
            ((Microsoft.CodeAnalysis.CSharp.Syntax.AssignmentExpressionSyntax)((Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionStatementSyntax)operationContext.Operation.Syntax).Expression).Left
        }
           , OperationKind.ExpressionStatement);
    }
}

我想找到所有持有类型IDataReader的变量的引用,确保在超出范围之前,在此变量中调用close方法。

我想分析的代码示例如下。

 class Program
{
    static void Main(string[] args)
    {
        IDataReader reader = null;
        try
        {

            Database db = DatabaseFactory.CreateDatabase("ApplicationConnection");



            reader = GetDataReader(db);
            while (reader.Read())
            {
                   //Do somethig with the data here
            }
            reader.Close();
        }
        catch (Exception)
        {

            throw;
        }
        finally
        {
            if (reader != null && !reader.IsClosed)
            {
                reader.Close();
            }
        }
    }
public static IDataReader GetDataReader(Database db)
    {
        DbCommand dbcmd = db.GetSqlStringCommand("some select statement to get data from oracle data base");
        var reader = db.ExecuteReader(dbcmd);
        return reader;
    }
}
c# roslyn-code-analysis
1个回答
0
投票

有一个非常简单的方法,它主要涉及忘记Close,并利用它是IDisposable的事实-这是这种情况的预期API。然后,它变得非常简单得多-如此简单,以至于a:您不需要专用的分析器,b:与IDisposable兼容的现有分析器可能为您完成了工作。

using var reader = GetDataReader(db);
while (reader.Read())
{
    //Do somethig with the data here
}

带有try/catch/ finally等;编译器将简单地通过using添加执行此操作所需的一切。请注意,对于较早的编译器,这需要是:

using (var reader = GetDataReader(db))
{
    while (reader.Read())
    {
        //Do somethig with the data here
    }
}

作为旁注:我强烈建议not与ADO.NET API对抗-这不是一种花费时间的有用方法;它是一种有效的方法。像Dapper这样的工具可以执行[[对您来说最常见的事情] >>,因此您无需编写此代码-并且它知道所有需要避免的极端情况。典型的Dapper用法可能是:

string region = ... var users = connection.Query<User>( "some * from Users where Region = @region", new { region } // parameters ).AsList();

该库在内部处理所有ADO.NET详细信息。
© www.soinside.com 2019 - 2024. All rights reserved.