无法访问方法(具有 ASP.NET 核心的 Azure 表)

Can't access method (Azure Tables with ASP.NET Core)

我正在尝试从另一个 class(我的视图控制器)访问一个方法,我在其中连接到 Azure 表并更新实体。

我的'controller'调用如下:

// this requires an object reference
HttpResponseMessage httpResponseMessage = AzureTableConn.UpdateTenantSettings(post);

这是我的 class,其中包含我与 Azure Tables 的连接,我从 Azure Key Vault 中提取连接字符串:

public class AzureTableConn
{
    public AzureTableConn(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    private IConfiguration Configuration { get; set; }

    private CloudTable TableConnection(string tableName)
    {
        var connectionString = Configuration["AzureTableStorageConnectionString"];
        var cloudStorageAccount = CloudStorageAccount.Parse(connectionString);
        CloudTableClient tableClient = cloudStorageAccount.CreateCloudTableClient();
        CloudTable cloudTable = tableClient.GetTableReference(tableName);
        return cloudTable;            
    }

    public HttpResponseMessage UpdateTenantSettings(TenantSettingsModel tenantSettingsModel)
    {
        CloudTable cloudTable = TableConnection("TenantSettings");
        Task<TableResult> mergeEntity = cloudTable.ExecuteAsync(TableOperation.Merge(tenantSettingsModel));
        return new HttpResponseMessage();
    }
}

我希望能够从我的控制器 class 调用 UpdateTenantSettings 方法,但它说我需要一个实例。这是有道理的,但是我不能在不向默认构造函数提供 IConfiguration 对象的情况下创建实例。我觉得自己陷入了陷阱 22 并且不知道如何绕过它。

我的意图是在我的应用程序中使用我的 AzureTableConn class,而不是每次我想 read/write 到 Azure 表时都创建它的新实例。我已经尝试将我的 AzureTableConn class 设置为静态,虽然这可以解决对象引用错误,但我在引用 IConfiguration 时遇到问题。我也试过将我的构造函数设置为 static 但这又打破了它并告诉我 "a static constructor must be parameterless".

我还尝试将以下内容添加到我的 Startup.cs 文件中:

services.Configure<AzureTableConnectionString>(Configuration);

其中 AzureTableConnectionString 定义为:

public class AzureTableConnectionString
{
    public string ConnectionString { get; set; }
}

但是,我不知道这是否正确或如何实现。

那么我如何才能将我的 Azure Key Vault 配置设置拉到 class 中,然后使用同一 class 中的方法重新使用与 Azure 表的连接,并从中访问这些方法另一个 class 我需要向 create/update/delete/etc.?

提供实体(数据)等参数

您可以让 ASP.NET 核心通过向 DI 容器注册 AzureTableConn 来为您处理这个问题,就像这样(在 ConfigureServices 中):

services.AddSingleton<AzureTableConn>();

为了在您的控制器中使用它,只需将它作为参数添加到控制器的构造函数中并存储它以备后用,如下所示:

public class SomeController : Controller
{
    private readonly AzureTableConn _azureTableConn;

    public SomeController(AzureTableConn azureTableConn)
    {
        _azureTableConn = azureTableConn;
    }

    public IActionResult SomeAction()
    {
        ...
        var httpResponseMessage = _azureTableConn.UpdateTenantSettings(post);
        ...
    }
}

在此示例中,您可以在控制器的任何操作中使用 _azureTableConn。因为我们使用了AddSingleton,所以每个控制器都会得到相同的实例,它只会被创建一次。

文档很好地解释了这一点:Dependency injection in ASP.NET Core

考虑创建抽象。

public interface IAzureTableConnection {
    Task<HttpResponseMessage> UpdateTenantSettings(TenantSettingsModel tenantSettingsModel);
}

通常建议避免耦合到 IConfiguration。相反,在组合根中获取您需要的内容并将其传递给从属 class.

Startup

private IConfiguration Configuration { get; set; }

public void ConfigureServices(IServiceCollection services) {

    //...

    var connectionString = Configuration["AzureTableStorageConnectionString"];
    var cloudStorageAccount = CloudStorageAccount.Parse(connectionString);
    CloudTableClient tableClient = cloudStorageAccount.CreateCloudTableClient();

    services.AddScoped<IAzureTableConnection>(_ => new AzureTableConnection(tableClient));

    //...
}

依赖的 class 将只需要依赖配置的 CloudTableClient

public class AzureTableConnection: IAzureTableConnection {
    private readonly CloudTableClient tableClient;

    public AzureTableConnection(CloudTableClient tableClient) {
        this.tableClient = tableClient;
    }

    private CloudTable TableConnection(string tableName) {
        CloudTable cloudTable = tableClient.GetTableReference(tableName);
        return cloudTable;            
    }

    public async Task<HttpResponseMessage> UpdateTenantSettings(TenantSettingsModel tenantSettingsModel) {
        CloudTable cloudTable = TableConnection("TenantSettings");
        var mergeEntity = await cloudTable.ExecuteAsync(TableOperation.Merge(tenantSettingsModel));

        //...do something with the result

        return new HttpResponseMessage();
    }
}

您的控制器将通过构造函数注入显式依赖于 IAzureTableConnection 抽象,并在需要时访问注入的实例

public class MyController : Controller {
    private readonly IAzureTableConnection tableConnection;

    public MyController(IAzureTableConnection tableConnection) {
        this.tableConnection = tableConnection;
    }

    public async Task<IActionResult> MyAction() {


        //...

        HttpResponseMessage httpResponseMessage = await tableConnection.UpdateTenantSettings(post);

        //...
    }
}