好吧,通过尝试错误,我发现了一种艰难的方式,即:
Client.Send(new { value = "NewValue" }, "set_MyProp");
是等效的代码:
conn.publish('set_MyProp',{value:'NewValue'});
注意“值”的大小写!!!单词不要大写!
更新
我创建了两个扩展方法,可以很容易地获取和设置属性值(还有一个WaitForConnection
在单元测试等同步场景中很有用)。
由于 XSockets(非常不幸)不是开源的,而且文档很少,我不得不猜测事情是如何工作的,所以如果我能够阅读源代码,我的扩展方法可能不会像它们那样高效和优雅,并且我从服务器读取属性的方法可能有点“小心”...如果有人知道如何改进它,请编辑答案或在评论部分提出建议:
public static class XSocketClientExtensions
{
public static bool WaitForConnection(this XSocketClient client, int timeout=-1) {
return SpinWait.SpinUntil(() => client.IsConnected, timeout);
}
public static void SetServerProperty(this XSocketClient client, string propertyName, object value) {
client.Send(new { value = value }, "set_" + propertyName);
}
public static string GetServerProperty(this XSocketClient client, string propertyName) {
var bindingName = "get_" + propertyName;
// why event name is lowercase?
var eventName = bindingName.ToLowerInvariant();
// we must be careful to preserve any existing binding on the server property
var currentBinding = client.GetBindings().FirstOrDefault(b => b.Event == eventName);
try {
// only one binding at a time per event in the client
if (currentBinding != null)
client.UnBind(bindingName);
var waitEvent = new ManualResetEventSlim();
string value = null;
try {
client.Bind(bindingName, (e) => {
value = e.data;
waitEvent.Set();
});
// we must "Trigger" the reading of the property thru its "event" (get_XXX)
client.Trigger(bindingName);
// and wait for it to arrive in the callback
if (waitEvent.Wait(5000))
return value;
throw new Exception("Timeout getting property from XSockets controller at " + client.Url);
} finally {
client.UnBind(bindingName);
}
} finally {
// if there was a binding already on the "property getter", we must add it back
if (currentBinding != null)
client.Bind(bindingName, currentBinding.Callback);
}
}
}
用法轻而易举:
// Custom controller
public class MyController : XSocketController
{
public int Age { get; set; }
public override void OnMessage(ITextArgs textArgs) {
this.SendToAll(textArgs);
}
}
// then in the client
var client = new XSocketClientEx("ws://127.0.0.1:4502/MyController", "*");
client.WaitForConnection(); // waits efficiently for client.IsConnected == true
client.SetServerProperty("Age", 15);
int age = Convert.ToInt32(client.GetServerProperty("Age"));
你可以跳过以下内容,这只是一个咆哮!
一些事情使得从一开始就很难确定它。JavaScript 客户端和 C# 客户端之间没有协议。因此,您在一种技术中学到的东西不会转化为另一种技术。在我自己的多语言客户端 API 上,我尝试让所有 API 的行为和外观都非常相似,即使不完全相同,所以代码几乎是可移植的。我有一个在 JavaScript、C# 和 Java 中看起来几乎相同的 API。
困扰我的差异是:
- 这些方法有不同的名称:
publish
在 JavaScript 中与Send
在 C# 中
- 参数以相反的顺序传递:
value, event
在 C# 中,event, value
在 JavaScript 中
本身没有区别,但是如果您在 C# 示例中使用“值”,它将不起作用,您必须使用“值”……我认为它不应该区分大小写…… 这样做的理由非常有说服力。那我就别吹牛了!