如何在XSockets中使用c#客户端API获取/设置属性
本文关键字:API 客户端 获取 属性 设置 XSockets | 更新日期: 2023-09-27 18:03:56
在XSockets服务器API中有一个关于如何使用JavaScript API获取/设置服务器控制器属性的示例
从客户端获取/设置属性
如果你有一个可以访问的带有公共getter或setter的属性客户端API的
中的getter/setter方法public string MyProp {get;set;}
上面的属性可以从客户端API中检索和更改(包括JavaScript和c#)。设置新值的示例JavaScript
conn.publish('set_MyProp',{value:'NewValue'});
查看客户端API获取更多信息。
但是客户端API页面上没有任何信息
我很难弄清楚JavaScript代码conn.publish('set_MyProp',{value:'NewValue'});
的等效c#客户端代码是什么
任何帮助都非常感激。
通过试错,我发现了这个困难的方法:
Client.Send(new { value = "NewValue" }, "set_MyProp");
相当于:
conn.publish('set_MyProp',{value:'NewValue'});
注意value的大小写!!不要把这个词大写!
我已经创建了两个扩展方法,这使得它很容易获得和设置属性值(也有一个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的行为和外观非常相似,如果不是完全相同的话,所以代码几乎是可移植的。我有一个API,看起来几乎相同的JavaScript, c#和Java。
困扰我的差异是:
- 方法有不同的名称:JavaScript中的
publish
与c#中的Send
- 参数以相反的顺序传递:
value, event
在c#中,event, value
在JavaScript中
我同意,JavaScript和c#之间的API应该更相似。从4.0开始,它们将同时支持pub/sub和rpc,并且在接口上具有相同的命名。
属性的设置/获取将有方法来帮助你,因为设置枚举和字符串是有区别的。API会有。(请注意,您将在1个连接上对n个控制器进行多路复用,这就是指定控制器名称的原因)
c#conn.Controller("NameOfController").SetEnum("name", "value");
conn.Controller("NameOfController").SetProperty("name", object);
JavaScript conn.nameofcontroller.setEnum('name', 'value');
conn.nameofcontroller.setProperty('name', object);
关于c#中大写"value"参数的错误…由于我们使用的是编译器为公共getter和setter创建的方法,value实际上是方法的参数,不应该大写。