简体   繁体   English

如何在XSockets中使用C#客户端API获取/设置属性

[英]How to Get/Set Properties using the C# client API in XSockets

In the XSockets Server API there is an example on how to get/set properties on the server controller using the JavaScript API 在XSockets Server API中,有一个示例,说明如何使用JavaScript API在服务器控制器上获取/设置属性。

Get/Set properties from the client APITop 从客户端API获取/设置属性

If you have a property with a public getter or setter you can access the getter/setter methods from the client API's 如果您拥有带有公共getter或setter的属性,则可以从客户端API的getter / setter方法访问

 public string MyProp {get;set;} 

The property above can be retrieved and changed from the client API's (both JavaScript and C#). 可以从客户端API(JavaScript和C#)中检索和更改上面的属性。 Example on how to set a new value from JavaScript 有关如何通过JavaScript设置新值的示例

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

See the client API's for more information. 有关更多信息,请参见客户端API。

But there's no information whatsoever on the Client API's page 但是客户端API的页面上没有任何信息

I'm having a hard-time figuring out what is the equivalent C# Client code for the JavaScript code conn.publish('set_MyProp',{value:'NewValue'}); 我很难确定JavaScript代码conn.publish('set_MyProp',{value:'NewValue'});的等效C#客户端代码是什么conn.publish('set_MyProp',{value:'NewValue'});

Any help is immensely appreciated. 非常感谢您的帮助。

Well, I've found out the hard way, by trial an error, that this: 好吧,通过尝试一个错误,我发现了一个困难的办法,那就是:

Client.Send(new { value = "NewValue" }, "set_MyProp");

Is the equivalent code to: 等效于以下代码:

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

Pay attention to the case of "value"!!! 注意“值”的情况!!! Don't capitalize the word! 不要大写这个词!

UPDATE UPDATE

I've created two extension methods which makes it very easy to get and set property values (there's also a WaitForConnection which is useful in somewhat synchronous scenarios like Unit Testing). 我创建了两个扩展方法,这些方法使获取和设置属性值变得非常容易(还有一个WaitForConnection ,在某些类似单元测试的同步场景中很有用)。

Since XSockets is (very unfortunately) not open source, and documentation is minimal, I have to guess how things work, so my extension methods may not be as efficient and elegant as they could be if I was able to read the source code, and I may have been a little too "careful" with my approach for reading properties from the server... If anyone knows how to improve it, please, edit the answer or suggest it on the comments section: 由于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);
        }
    }
}

Usage is a breeze: 用法轻而易举:

// 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"));

You can skip the following, it is just a rant! 您可以跳过以下内容,这简直就是!

A few things made it difficult to nail it down from the beginning. 一些事情使得从一开始就很难确定它。 There's no agreement between the JavaScript client and the C# client. JavaScript客户端和C#客户端之间没有协议。 So what you learn in one does not translate to the other technology. 因此,您从一种中学到的知识不会转化为另一种技术。 On my own multi-language client APIs I try to make all APIs behave and look very similar, if not identical, so code is almost portable. 在我自己的多语言客户端API上,我尝试使所有API都表现出来并且看起来非常相似(如果不相同),因此代码几乎可以移植。 I've got an API that looks nearly identical in both JavaScript, C# and Java. 我有一个在JavaScript,C#和Java中看起来几乎相同的API。

The differences that bothered me are: 困扰我的差异是:

  1. The methods have different names: publish in JavaScript vs Send in C# 这些方法具有不同的名称:在JavaScript中publish与在C#中Send
  2. The parameters are passed in reversed order: value, event in C#, event, value in JavaScript 参数以相反的顺序传递: value, event C#中的event, value JavaScript中的event, value
  3. Not a difference in itself, but if you use 'Value' in the C# example it won't work, you must use 'value'... I don't believe it should have been case sensitive... 本身没有区别,但是如果您在C#示例中使用“值”将不起作用,则必须使用“值” ...我不认为它应该区分大小写... the reasoning for this is quite convincing. 这样做的理由令人信服。 I'll quit quibbling then! 那我就别再吵了!

I agree, the API's between JavaScript and C# should have been more similar. 我同意,JavaScript和C#之间的API应该更相似。 As of 4.0 they will both support both pub/sub and rpc and have the same naming on the interfaces. 从4.0开始,它们都将支持pub / sub和rpc,并且在接口上具有相同的命名。

The setting/getting of properties will have methods that help you since there is a difference in setting Enums and Strings for example. 设置/获取属性将具有帮助您的方法,因为例如设置Enums和Strings有所不同。 So the API will have methods like.. (note that you will multiplex over n controllers on 1 connections, that why the controller name is specified) 因此,API将具有以下方法:(请注意,您将在1个连接上对n个控制器进行多路复用,这就是为什么要指定控制器名称的原因)

C# C#

conn.Controller("NameOfController").SetEnum("name", "value");
conn.Controller("NameOfController").SetProperty("name", object);

JavaScript JavaScript的

conn.nameofcontroller.setEnum('name', 'value');
conn.nameofcontroller.setProperty('name', object);

Regarding the error if you capitalize the "value" parameter in C#... Since we use the methods that the compiler created for public getters and setters value is really a parameter on a method and should not ever be capitalized. 关于如果在C#中将“ value”参数大写的错误,由于我们使用的是编译器为公共getter和setters创建的方法,value实际上是方法上的参数,永远不要大写。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM