gpt4 book ai didi

c# - 将 IDictionary> 转换为 IObservable>

转载 作者:太空宇宙 更新时间:2023-11-03 23:18:32 25 4
gpt4 key购买 nike

我有一个函数可以用另一个实体替换存储库(例如数据库)中的单个实体。这将返回一个任务,其结果指示替换是否成功。

// Single Replace
Task<bool> Replace(Entity e, Entity Other);

现在假设我想创建相同的函数,但允许替换多个实体。我对函数签名的想法是:

// Multiple Replace
IObservable<KeyValuePair<Entity, bool>> Replace(IDictionary<Entity, Entity> Map);

Map 包含一个字典,其键是要替换的实体,它的值是要替换旧实体的新实体。

这个Map字典的每个KeyValuePair应该返回一个KeyValuePair ,其中key对应Map.Key(=要被替换的实体),Value是一个bool,表示替换是否成功不是。

我想将其作为流返回,因此我选择了 IObservable< KeyValuePair< Entity,bool >>,为每个可用的结果推出 KeyValuePair< Entity,bool >。

目前,我只想让“多次替换”功能使用“单一替换”功能进行转换;但是我怎样才能进行这些调用并以所需的格式返回结果呢?

Task<bool> Replace(Entity e, Entity Other)
{
// ... do the work ...
}

IObservable<KeyValuePair<Entity, bool>> Replace(IDictionary<Entity, Entity> Map)
{
// How this should work:
// for each KeyValuePair in Map, call the Single Replace function
// and - once available - return its result (bool) mapped to the Entity in the
// resulting Observable stream

IDictionary<Entity, Task<bool>> dict = Map.ToDictionary(x => x.Key, x => Replace(x.Key, x.Value));

// .. now what? How can I now convert the dict into an IObservable<KeyValuePair<Entity,bool>> ?

}

不胜感激!

最佳答案

没有看到好的Minimal, Complete, and Verifiable example这清楚地表明了你在做什么,尤其是你打算如何实现 IObservable<T>从你的方法返回的对象,不可能提供具体的建议。不过,我可以提供一些建议,至少应该为您指明一个有用的方向。

首先,我建议拥有一个Task<Tuple<Entity, bool>>更有用。 (或 Task<KeyValuePair<Entity, bool>> ,尽管我不太喜欢将与字典相关的类型用于非字典相关的代码……也就是说,您实际上只是在配对事物而不是真正的键/值配对)。这样,当任务完成时,您可以从任务本身了解所需的所有信息。

这可以通过一个简单的辅助方法来完成,例如:

async Task<Tuple<Entity, bool>> ReplaceAsync(Entity e, Entity other)
{
return Tuple.Create(e, await Replace(e, other));
}

我用了Tuple在这里,但当然您可以为此目的创建一个命名类型,这样做实际上可能有助于提高代码的可读性。

完成后,您可以枚举输入字典(或其他更合适的集合 :) )中的所有项目,然后使用 Task.WhenAny()以迭代方式删除和发布每个已完成的项目:

IObservable<Tuple<Entity, bool>> Replace(IDictionary<Entity, Entity> Map)
{
Task<Tuple<Entity, bool>>[] tasks = new Task<Tuple<Entity, bool>>(Map.Count);
int i = 0;

foreach (var kvp in Map)
{
tasks[i++] = ReplaceAsync(kvp.Key, kvp.Value);
}

// Create the IObservable object somehow. Make sure it has the
// array of tasks in it. E.g. (see below for TaskObservable example)

TaskObservable<Tuple<Entity, bool>> observable =
new TaskObservable<Tuple<Entity, bool>>(tasks);

// Now, start running the observable object. Note: not really all that great
// to ignore the returned Task object but without more context in your question
// I can't offer anything more specific. You will probably want to store the
// Task object *somewhere*, await it, wrap all that in try/catch, etc. to
// make sure you are correctly monitoring the progress of the task.
var _ = observable.Run();

return observable;
}

IObservable<T>可能看起来像:

class TaskObservable<T> : IObservable<T>
{
private class ObserverItem : IDisposable
{
public readonly IObserver<T> Observer;
public readonly TaskObservable<T> Owner;

public ObserverItem(IObserver<T> observer, TaskObservable<T> owner)
{
Observer = observer;
Owner = owner;
}

public void Dispose()
{
if (!Owner._observerItems.Contains(this))
{
throw new InvalidOperationException(
"This observer is no longer subscribed");
}

Owner._observerItems.Remove(this);
}
}

private readonly Task<T>[] _tasks;
private readonly List<ObserverItem> _observerItems = new List<ObserverItem>();

public TaskObservable(Task<T>[] tasks)
{
_tasks = tasks;
}

public IDisposable Subscribe(IObserver<T> observer)
{
ObserverItem item = new ObserverItem(observer, this);

_observerItems.Add(item);
return item;
}

private void Publish(T t)
{
foreach (ObserverItem item in _observerItems)
{
item.Observer.OnNext(t);
}
}

private void Complete()
{
foreach (ObserverItem item in _observerItems)
{
item.Observer.OnCompleted();
}
}

async Task Run()
{
for (int i = 0; i < _tasks.Length; i++)
{
Task<T> completedTask = await Task.WhenAny(tasks);

Publish(completedTask.Result);
}

Complete();
}
}

关于c# - 将 IDictionary<T, Task<bool>> 转换为 IObservable<KeyValuePair<T, bool>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36338234/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com