在C#中从getter或setter调用异步方法最优雅的方法是什么?
这里有一些伪代码可以帮助解释自己.
async Task<IEnumerable> MyAsyncMethod()
{
return await DoSomethingAsync();
}
public IEnumerable MyList
{
get
{
//call MyAsyncMethod() here
}
}
Run Code Online (Sandbox Code Playgroud) 在C#中,是否有内联快捷方式来实例化只包含一个项目的List <T>.
我现在正在做:
new List<string>( new string[] { "title" } ))
Run Code Online (Sandbox Code Playgroud)
在任何地方使用此代码会降低可读性 我曾想过使用这样的实用方法:
public static List<T> SingleItemList<T>( T value )
{
return (new List<T>( new T[] { value } ));
}
Run Code Online (Sandbox Code Playgroud)
所以我能做到:
SingleItemList("title");
Run Code Online (Sandbox Code Playgroud)
有更短/更清洁的方式吗?
谢谢.
我有一个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
我已经学会了在我的存储库中延迟加载属性.现在我想这样做,但我还需要从网页加载一些东西(使用Httpclient),这意味着我的属性将是异步的.
public async Task<List<NewsModel>> News
{
get
{
if (_news == null)
{
CacheProvider cache = new CacheProvider();
object cachedNews = cache.Get("news");
if (cachedNews == null)
{
var client = new HttpClient();
// await HttpResponse
}
}
return _news;
}
set
{
_news = value;
}
}
Run Code Online (Sandbox Code Playgroud)
然而,视觉工作室告诉我
"修饰符异步对此项无效"
同时在第一行突出显示"新闻"一词.
是否有可能做到这一点?或者我必须编写一个单独的方法?
TL;DR:Autofac 支持类似 AutoFixture 的fixture.Get()机制吗?
我正在使用 Autofac 并且需要调用异步工厂方法,如下所示:
class AppModel
{
public static async Task<AppModel> CreateAsync(IDependency x, IDependency2 y)
{ ... }
}
Run Code Online (Sandbox Code Playgroud)
对我来说执行此类方法并由 Autofac 提供参数的最简单方法是什么?即,我希望能够做类似的事情:
Task<AppModel> creationTask = <some autofaccery>(AppModel.CreateAsync);
var appModel = await creationTask();
Run Code Online (Sandbox Code Playgroud)
其中<some autofaccery>表示与ContainerBuilder和/或IContainer和/或某种形式的生成的委托或类似的交互的某种机制,它本质上是简洁的,并且使我无法显式指定工厂方法的参数。即,我想避免像 atm 那样显式解析每个参数 [和/或必须在依赖项发生变化时更新它们]:
var appModel = await AppModel.CreateAsync(
container.Resolve<IDependency>(),
container.Resolve<IDependency2>());
Run Code Online (Sandbox Code Playgroud)
我位于基础设施组件领域,靠近组合根,可能会以编程方式定义组件注册和/或执行其他应限制在此处的肮脏操作。我不介意参与反射,因为它只被调用一次。
关键是我确实需要观察Exception所产生的任何结果Task。
这Task<T>在很大程度上是一个转移注意力的话题,但重点是,遵循定义同步工厂方法并让 Autofac 完成工作的正常模式不会成功(至少不会直接),即我不能只是改变它到:
public static AppModel CreateAsync(IDependency x, IDependency2 y)
{ ... } …Run Code Online (Sandbox Code Playgroud) public Data GetCurrent(Credentials credentials)
{
var data = new Lazy<Data>(() => GetCurrentInternal(credentials));
try
{
return data.Value;
}
catch (InvalidOperationException ex)
{
throw ex.InnerException;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我将呼叫更改为以下内容:
var data = new Task<Data>(() => GetCurrentInternal(credentials));
Run Code Online (Sandbox Code Playgroud)
有什么变化吗?我宁愿Task过Lazy?怎么样Dispose()和catch(Exception)?