- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个函数可以用另一个实体替换存储库(例如数据库)中的单个实体。这将返回一个任务,其结果指示替换是否成功。
// Single Replace
Task<bool> Replace(Entity e, Entity Other);
现在假设我想创建相同的函数,但允许替换多个实体。我对函数签名的想法是:
// Multiple Replace
IObservable<KeyValuePair<Entity, bool>> Replace(IDictionary<Entity, Entity> Map);
Map 包含一个字典,其键是要替换的实体,它的值是要替换旧实体的新实体。
这个Map字典的每个KeyValuePair应该返回一个KeyValuePair
我想将其作为流返回,因此我选择了 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/
我的 ViewModel 上有一处特性那是类型 IDictionary .我正在查看 ViewModel 上的属性列表并使用反射来确定它是否是字典。 目前我有: if (typeof(IDiction
我有一个 IDictionary 字段,我想通过 IDictionary 类型的属性公开它转换非常困难,因为我不知道我能做什么 .Cast<>() IDictionary to. 最好的我有: IDi
我有一个用作字典的 C# 类,所以我现在正在支持 IDictionary。 除了属性 Keys 和 Values 之外一切都很好: ICollection Keys { get; } ICollect
当一个方法有两个重载时,一个接受 IDictionary 另一个接受 IDictionary ,将 new Dictionary() 传递给它被认为是不明确的。但是,如果将两个重载更改为接受 IEnu
我有一个我不满意的方法,你能告诉我如何做得更好吗? public Foo WithBar(IDictionary parameters) { var strStrDict = new Dict
以下代码自HashSet起有效工具 IEnumerable : IEnumerable edges = new HashSet(); 但是如果我尝试使用与字典中键入的值相同的值,我会得到一个编译错误:
我有一个返回 IDictionary > 的函数. 我有另一个函数需要 IDictionary > . 我需要将第一个函数的返回传递给第二个函数。 编译器不想将第一个隐式转换为第二个。那么如何在 O(
我认为转换 IDictionary> 相当简单反对 IDictionary> , 但是 var val = (IDictionary>)Value; 抛出 System.InvalidCastExce
我正在使用反射和递归进行一些通用对象比较。递归方法在每个步骤中都需要一些类型信息,这些信息由调用者提供。有一次我知道下一个属性是 Dictionary ,我想发送正确的类型。我想到了这个: Type
很多消息来源都在谈论这个问题,但我不太理解这个概念。 IDictionary 是通用的,它的类型安全等。 当我深入研究 EntityFrameworkv5 时,我看到一个属性在 LogEntry 类中
我创建了一个 IDictionary 扩展来将 IDictionary Exception.Data 值写入字符串。 扩展代码: public static class DictionaryExten
我们有一个应用程序在多个 Dictionary 中保存大量对象,其中一些对象在应用程序的生命周期中不断增长(交易应用程序有很多工具和不断增长的订单/交易) . 由于大型对象堆的碎片,我们遇到了 Out
我在外部类中有以下方法 public static void DoStuffWithAnimals(IDictionary animals) 在我的调用代码中,我已经有一个 Dictionary对象,
通过今天的一些随机对象创建,我遇到了一个 Dictionary 的简洁小快捷方式.以下赋值是编译器快捷方式还是 Dictionary 的一个特性? . IDictionary items = { {
我正在测试这样的对象: if (item is IDictionary) 但这并不匹配所有其他类型组合 , 等等…… 我只想知道它是否实现了接口(interface),而不管它使用的是什么泛型。 我找
有谁知道序列化实现 IDictionary 的对象的创造性方法吗? ...没有实现新类(class)? 最佳答案 如果类实现了IDictionary是可序列化的(如 Dictionary )和 K和
我这辈子都弄不明白。假设我有以下两个字典对象: // Assume "query" is a LINQ queryable. Dictionary d1 = query.ToDictionary(k
这个问题在这里已经有了答案: Remove from Dictionary by Key and Retrieve Value (6 个答案) 关闭 2 年前。 我想知道是否可以通过键删除一个 ID
在 TagBuilder 和其他类中,我可以这样写: var tr = new TagBuilder("HeaderStyle"){InnerHtml = html, [IDictionary Att
取下面这段代码 var dictionary = new Dictionary { ["A"] = 1, ["B"] =
我是一名优秀的程序员,十分优秀!