Reactive Extensions带有许多辅助方法,用于将现有事件和异步操作转换为可观察对象,但是如何从头开始实现IObservable <T>?
IEnumerable有一个可爱的yield关键字,使其实现起来非常简单.
实现IObservable <T>的正确方法是什么?
我需要担心线程安全吗?
我知道有人支持在特定的同步上下文中回调,但这是否是我作为IObservable <T>作者需要担心或者以某种方式内置的内容?
更新:
这是Brian的F#解决方案的C#版本
using System;
using System.Linq;
using Microsoft.FSharp.Collections;
namespace Jesperll
{
class Observable<T> : IObservable<T>, IDisposable where T : EventArgs
{
private FSharpMap<int, IObserver<T>> subscribers =
FSharpMap<int, IObserver<T>>.Empty;
private readonly object thisLock = new object();
private int key;
private bool isDisposed;
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing && !isDisposed)
{
OnCompleted();
isDisposed = true;
}
}
protected void OnNext(T value)
{
if (isDisposed) …Run Code Online (Sandbox Code Playgroud) 用于解释Reactive Extensions(Rx)功能的一个主要示例是将现有鼠标事件组合成一个表示鼠标拖动过程中增量的新"事件":
var mouseMoves = from mm in mainCanvas.GetMouseMove()
let location = mm.EventArgs.GetPosition(mainCanvas)
select new { location.X, location.Y};
var mouseDiffs = mouseMoves
.Skip(1)
.Zip(mouseMoves, (l, r) => new {X1 = l.X, Y1 = l.Y, X2 = r.X, Y2 = r.Y});
var mouseDrag = from _ in mainCanvas.GetMouseLeftButtonDown()
from md in mouseDiffs.Until(
mainCanvas.GetMouseLeftButtonUp())
select md;
Run Code Online (Sandbox Code Playgroud)
资料来源: Matthew Podwysocki的反应框架系列介绍.
在MVVM中,我通常努力使我的.xaml.cs文件尽可能为空,并且使用viewmodel中的命令从视图中连接事件的一种方法纯粹是在标记中使用一种行为:
<Button Content="Click Me">
<Behaviors:Events.Commands>
<Behaviors:EventCommandCollection>
<Behaviors:EventCommand CommandName="MouseEnterCommand" EventName="MouseEnter" />
<Behaviors:EventCommand CommandName="MouseLeaveCommand" EventName="MouseLeave" />
<Behaviors:EventCommand CommandName="ClickCommand" EventName="Click" />
</Behaviors:EventCommandCollection>
</Behaviors:Events.Commands>
</Button>
Run Code Online (Sandbox Code Playgroud)
资料来源: …
假设我有以下解决方案,同一个代码的多个版本,每个版本都针对不同的框架,我想从中生成一个nuget包.
SharedLib.sln
SharedLib.Net35.csproj
packages.config
SharedLib.Net40.csproj
packages.config
SharedLib.Phone.csproj
packages.config
SharedLib.SL4.csproj
packages.config
Run Code Online (Sandbox Code Playgroud)
预期的nupkg具有以下结构
SharedLib.1.0.nupkg
lib/net35/SharedLib.dll
lib/net40/SharedLib.dll
lib/sl4-wp/SharedLib.dll
lib/sl4/SharedLib.dll
Run Code Online (Sandbox Code Playgroud)
nuget.exe pack SharedLib.SL4.csproj 将自动确定目标框架是SilverLight4并将二进制文件放入 lib/sl4
我知道我可以添加一个SharedLib.SL4.nuspec带有一个<file>部分的文件来包含来自其他项目的二进制文件,但是有没有办法让nuget自动将组合的解决方案输出放到适当的结构中(并且还检测来自所有项目的packages.config中的依赖项?
我有一个带有CoerceValueCallback的DependencyProperty的控件.此属性绑定到模型对象上的属性.
将控件属性设置为导致强制的值时,Binding会将未校正的值推送到模型对象.控件上的属性值被正确强制.
如何让Binding将强制值推送到模型对象?
void Initialize()
{
UIObject ui = new UIObject();
ModelObject m = new ModelObject();
m.P = 4;
Binding b = new Binding("P");
b.Source = m;
b.Mode = BindingMode.TwoWay;
Debug.WriteLine("SetBinding");
// setting the binding will push the model value to the UI
ui.SetBinding(UIObject.PProperty, b);
// Setting the UI value will result in coercion but only in the UI.
// The value pushed to the model through the binding is not coerced.
Debug.WriteLine("Set to -4");
ui.P …Run Code Online (Sandbox Code Playgroud) 通常,当您订阅值的更改时,您也有兴趣知道初始值.我希望我的IObservable缓存最新(或初始)值并在订阅时推送该值.
当使用普通事件时,我经常会得到看起来像的代码
x.SomeEvent += SomeEventHandler;
SomeEventHandler(x, EventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)
使用IObservable我希望用推送初始值的东西包装事件.如果我有多个订阅者,他们应该在订阅时收到最新的值我有一些代码,如果我在创建IObservable之后立即订阅,但是如果事件在订阅之前触发则不会:
class Program
{
static void Main()
{
var s = new Source { Value = 1 };
var values = Observable.Return(s.Value).Concat(
Observable.FromEvent(
h => s.ValueChanged += h,
h => s.ValueChanged -= h)
.Select(_ => s.Value));
using (values.Subscribe(Console.WriteLine))
{
s.Value = 2; // prints 1,2 as expected
}
using (values.Subscribe(Console.WriteLine))
{
s.Value = 3; // prints 1,3 - expected 2,3
}
}
}
class Source
{
private int _value;
public int Value
{ …Run Code Online (Sandbox Code Playgroud) 假设我在不同域(mydomain.com)上的页面上,并且相对URL仅存在于代码中(不在DOM中)
如何在javascript中完全组合两个任意网址?
var a = 'http://example.com/some/path/';
var b = '../other/path/';
var c = magicUrlCombine(a,b);
assert(c == 'http://example.com/some/other/path/');
Run Code Online (Sandbox Code Playgroud)
它也应该有效
var a = 'http://example.com/some/path/';
var b = 'http://pink-unicorns.com/some/other/path/';
var c = magicUrlCombine(a,b);
assert(c == 'http://pink-unicorns.com/some/other/path/');
Run Code Online (Sandbox Code Playgroud)
编辑:
我正在寻找一个完全通用的功能,用于将绝对URL与任意URL组合.与浏览器用于解析链接的逻辑相同,但用于不在页面HTML中和/或不相对于当前location.href的URL.
var a = 'http://example.com/a/b/c/';
var b = '../d/e/';
assert(c == 'http://example.com/a/b/d/e/')
Run Code Online (Sandbox Code Playgroud)
要么
var b = '/f/g/';
assert(c == 'http://example.com/f/g/')
Run Code Online (Sandbox Code Playgroud)
要么
var b = 'http://jquery.com/h/i/';
assert(c == 'http://jquery.com/h/i/')
Run Code Online (Sandbox Code Playgroud)
编辑2:
node.js有一个具有正确功能的url模块,但我还没有找到一种在客户端重用它的好方法.(如何在客户端使用node.js模块系统)
我设法通过破解我的方式使其工作,但这不是一个真正的解决方案我觉得放入生产网站很舒服.Hackety hack