我有一个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直接在构造函数内调用.可能有很多(甚至是明显的)边缘情况和反对它的理由,我只是想不出来.我也在寻找解释,但似乎找不到任何解释.
我有一个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
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 负责处理。
不是这样吗?我错过了什么吗?
在 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) 我有一个用于获取一些信息的服务,并且该方法在链中有一堆异步调用。
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# ×4
async-await ×3
asp.net-core ×2
asp.net-mvc ×1
autofac ×1
constructor ×1
dapper ×1
startup ×1