相关疑难解决方法(0)

构造函数可以异步吗?

我有一个Silverlight项目,我试图在构造函数中填充一些数据:

public class ViewModel
{
    public ObservableCollection<TData> Data { get; set; }

    async public ViewModel()
    {
        Data = await GetDataTask();
    }

    public Task<ObservableCollection<TData>> GetDataTask()
    {
        Task<ObservableCollection<TData>> task;

        //Create a task which represents getting the data
        return task;
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,我收到一个错误:

修饰符async对此项目无效

当然,如果我在标准方法中包装并从构造函数中调用它:

public async void Foo()
{
    Data = await GetDataTask();
}
Run Code Online (Sandbox Code Playgroud)

它工作正常.同样,如果我使用旧的由内而外的方式

GetData().ContinueWith(t => Data = t.Result);
Run Code Online (Sandbox Code Playgroud)

这也有效.我只是想知道为什么我们不能await直接在构造函数内调用.可能有很多(甚至是明显的)边缘情况和反对它的理由,我只是想不出来.我也在寻找解释,但似乎找不到任何解释.

c# constructor async-await

262
推荐指数
3
解决办法
13万
查看次数

避免所有DI反模式需要异步初始化的类型

我有一个Connections需要异步初始化的类型.这种类型的实例被其他几种类型(例如Storage)消耗,每种类型也需要异步初始化(静态,不是每个实例,并且这些初始化也依赖于Connections).最后,我的逻辑类型(例如Logic)使用这些存储实例.目前使用Simple Injector.

我尝试了几种不同的解决方案,但总有一种反模式存在.


显式初始化(​​时间耦合)

我目前使用的解决方案有Temporal Coupling反模式:

public sealed class Connections
{
  Task InitializeAsync();
}

public sealed class Storage : IStorage
{
  public Storage(Connections connections);
  public static Task InitializeAsync(Connections connections);
}

public sealed class Logic
{
  public Logic(IStorage storage);
}

public static class GlobalConfig
{
  public static async Task EnsureInitialized()
  {
    var connections = Container.GetInstance<Connections>();
    await connections.InitializeAsync();
    await Storage.InitializeAsync(connections);
  }
}
Run Code Online (Sandbox Code Playgroud)

我已经将Temporal Coupling封装成一种方法,所以它并没有那么糟糕.但是,它仍然是一个反模式,而不是像我想的那样可维护.


抽象工厂(同步异步)

常见的解决方案是抽象工厂模式.但是,在这种情况下,我们正在处理异步初始化.因此,我可以通过强制初始化同步运行使用抽象工厂,但这会采用同步异步反模式.我真的不喜欢异步同步方法,因为我有几个存储空间,在我当前的代码中,它们都是同时初始化的; 由于这是一个云应用程序,将其更改为串行同步会增加启动时间,并且由于资源消耗,并行同步也不理想.


异步抽象工厂(不正确的抽象工厂用法)

我也可以使用Abstract Factory和异步工厂方法.但是,这种方法存在一个主要问题.正如马克·西曼(Mark …

dependency-injection initialization abstract-factory async-await simple-injector

29
推荐指数
2
解决办法
1484
查看次数

注入 IDbConnection 与 IDbConnectionFactory

TLDR:注入连接工厂与 IDbConnection 本身的原因是什么。

我目前正在 .net MVC 中使用 Autofac 将 IDbConnection 的实例注入到我的存储库类中,以便与 Dapper 一起使用,如下所示:

Autofac设置:

builder.Register<IDbConnection>(ctx => new
    SqlConnection(conSettings.ConnectionString)).InstancePerRequest();
Run Code Online (Sandbox Code Playgroud)

回购:

public ClientRepository(IDbConnection connection)
{
    _connection = connection;
}

public async Task<IEnumerable<Client>> GetAsync()
{
    string query = "SELECT * FROM Clients";
    return (await _connection.QueryAsync<Client>(query)).ToList();
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,这对我来说一直很好,但我有点担心连接保持打开状态而不是被处理掉。

我在该主题上找到的每篇文章都以有人建议传入连接工厂并在 using 语句中调用它而告终,而没有真正提及为什么我当前的设置“不好”。

据我所知,每个请求都应该得到它自己的 IDbConnection,其中 Dapper 负责打开和关闭连接,而 Autofac 负责处理。

不是这样吗?我错过了什么吗?

c# asp.net-mvc autofac dapper

7
推荐指数
1
解决办法
3870
查看次数

IServiceCollection.AddScoped,委托为异步操作

在 IServiceCollection 上,当您必须通过计算服务的某些步骤来检索服务时,为注册字符串服务 AddTransiet、AddScoped、AddSingleton 提供的方法不允许您使用 async-await 构造。

我想知道制作异步版本是否是一种有效的方法。

internal static IServiceCollection AddScopedResolveAsync<TService>(this IServiceCollection serviceCollection, Func<IServiceProvider, Task<TService>> func)
    => serviceCollection.AddScoped(func);
Run Code Online (Sandbox Code Playgroud)

然后使用它

services.AddScopedResolveAsync<IMyService>(async serviceProvider =>
{
    await something;

    return new MyService();
});
Run Code Online (Sandbox Code Playgroud)

c# asp.net-core

7
推荐指数
1
解决办法
332
查看次数

在启动时调用 AddTransient 中的异步方法 - Asp.Net Core

我有一个用于获取一些信息的服务,并且该方法在链中有一堆异步调用。

public interface IFooService
{
    Task<IFoo> GetFooAsync();
}
Run Code Online (Sandbox Code Playgroud)

具体类,

public class FooService : IFooService
{
    public async Task<IFoo> GetFooAsync()
    {
        // whole bunch of awaits on async calls and return IFoo at last
    }
}
Run Code Online (Sandbox Code Playgroud)

我在 StartUp 上注册了这个服务,

services.AddTransient<IFooService, FooService>();
Run Code Online (Sandbox Code Playgroud)

此服务注入了其他几个服务。其中之一,

public class BarService : IBarService
{
    private readonly IFooService _fooService;

    public BarService(IFooService fooService)
    {
        _fooService = fooService;
    }

    public async Task<IBar> GetBarAsync()
    {
        var foo = await _fooService.GetFooAsync();

        // additional calls & processing
        var bar = SomeOtherMethod(foo);

        return bar; …
Run Code Online (Sandbox Code Playgroud)

c# startup async-await asp.net-core

6
推荐指数
1
解决办法
2573
查看次数