2

在 XSockets Server API 中有一个关于如何使用JavaScript API在服务器控制器上获取/设置属性的示例

从客户端 APITop 获取/设置属性

如果您有一个带有公共 getter 或 setter 的属性,您可以从客户端 API 访问 getter/setter 方法

public string MyProp {get;set;}

可以从客户端 API(JavaScript 和 C#)检索和更改上面的属性。关于如何从 JavaScript 设置新值的示例

conn.publish('set_MyProp',{value:'NewValue'});

有关更多信息,请参阅客户端 API。

但是客户端 API 页面上没有任何信息

我很难弄清楚 JavaScript 代码的等效 C# 客户端代码是什么conn.publish('set_MyProp',{value:'NewValue'});

非常感谢任何帮助。

4

2 回答 2

3

好吧,通过尝试错误,我发现了一种艰难的方式,即:

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。

困扰我的差异是:

  1. 这些方法有不同的名称:publish在 JavaScript 中与Send在 C# 中
  2. 参数以相反的顺序传递:value, event在 C# 中,event, value在 JavaScript 中
  3. 本身没有区别,但是如果您在 C# 示例中使用“值”,它将不起作用,您必须使用“值”……我认为它不应该区分大小写…… 这样做的理由非常有说服力。那我就别吹牛了!
于 2014-05-18T00:36:47.803 回答
2

我同意,JavaScript 和 C# 之间的 API 应该更相似。从 4.0 开始,它们将同时支持 pub/sub 和 rpc,并且在接口上具有相同的命名。

属性的设置/获取将具有帮助您的方法,因为例如设置 Enums 和 Strings 是不同的。因此 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 实际上是方法的参数,不应该大写。

于 2014-05-18T07:06:39.453 回答