我已经能够从一个html页面,aspx页面和一个Xamarin客户端创建和接收来自SignalR中心的消息,这是我在Visual Studio中使用Xamarin使用Microsoft.AspNet.SignalR.Client v2.4.1时真正需要它的应用程序2017.一旦我的Xamarin应用程序验证用户我开始连接到集线器,接下来我连接一个事件来接收消息。所有这一切都很好,我可以在Android应用程序中接收消息,无论当前活动是什么活动,这要归功于所连接的事件。现在我已经开始工作了,我希望能够从客户端向集线器发送消息,而无需创建到集线器的另一个连接。我看过静态类,但无法实现这一点。我的代码是:
这是用户通过身份验证后执行的代码:
// Start SignalR connection
Client client = new Client(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
await client.Connect();
// Wire up the message received event
client.OnMessageReceived += (sender2, message) => RunOnUiThread(() => showMessage(message));
从这里,用户可以从视图导航到视图,并且能够通过事件和showMessage
方法从集线器接收消息。这一切都完美无瑕。
我的客户端代码:此代码是从堆栈溢出工作示例中复制的,我将其修改为我的要求。
namespace ChatClient.Shared
{
class Client
{
private readonly string _platform;
private readonly HubConnection _connection;
private readonly IHubProxy _proxy;
public event EventHandler<string> OnMessageReceived;
public Client(string platform, string username)
{
string _username = "username=" + username;
_platform = platform;
_connection = new HubConnection("https://Example.com/SignalRhub", _username);
_proxy = _connection.CreateHubProxy("chathub");
}
public async Task Connect()
{
await _connection.Start(); _proxy.On("broadcastMessage", (string platform, string message) =>
{
if (OnMessageReceived != null)
OnMessageReceived(this, string.Format("{0}: {1}", platform, message));
});
Send("Connected");
}
public async Task<List<string>> ConnectedUsers()
{
List<string> Users = await _proxy.Invoke<List<string>>("getConnectedUsers");
return Users;
}
public Task Send(string message)
{
return _proxy.Invoke("Send", _platform, message);
}
}
}
现在我需要做的是使用登录后创建的连接向集线器发送消息,以便分发给所有连接的用户。我无法弄清楚如何做到这一点,我尝试使用静态类并尝试使用我在网上找到的方法,但似乎没有任何效果。
我的中心代码:
public class ChatHub : Hub
{
private static readonly List<User> Users = new List<User>();
public override Task OnConnected()
{
string userName = Context.QueryString["username"];
string firstname = Context.QueryString["firstname"];
string lastname = Context.QueryString["lastname"];
string connectionId = this.Context.ConnectionId;
var user = new User();
user.Name = userName;
user.ConnectionIds = connectionId;
try
{
Users.Add(user);
}
catch (Exception ex)
{
var msg = ex.Message;
}
// send list of connected users to client as a test
Send("Welcome " + userName, "Connected users are:");
foreach (var display in Users)
{
Send("",display.Name.ToString());
}
// test sending to a specific user
SendOne(connectionId, userName, "This is to a specific user.");
return base.OnConnected();
}
public override Task OnDisconnected(bool stopped)
{
string userName = Context.User.Identity.Name;
string connectionId = Context.ConnectionId;
var item = Users.Find(x => x.ConnectionIds == connectionId);
Send(item.Name , " disconnected.");
Users.Remove(item);
return base.OnDisconnected(true);
}
public void SendOne(string connectionId, string userName, string message)
{
Clients.Client(connectionId).broadcastMessage(userName, message);
}
public void Send(string name, string message)
{
// Call the broadcastMessage method to update clients.
Clients.All.broadcastMessage(name, message);
}
public List<string> getConnectedUsers()
{
List<string> UserNames = new List<string>();
foreach (var ConnectedUser in Users)
{
UserNames.Add(ConnectedUser.Name );
}
return UserNames;
}
}
我将在集线器中做很多其他事情,但是现在我需要让客户端发送消息而不创建另一个连接
有没有办法可以访问用户在其他视图/活动中进行身份验证后创建的连接?
*更新*
我根据Leo Zhu的答案更改了我的代码,但是当我尝试在线上实例化类时出现错误:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
GetInstance does not exist
实际上是这样的。不知道为什么它没有“找到”。
*更新*
从行中删除了new
关键字:
Client client = new Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
它现在写道:
Client client = Client.GetInstance(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username);
奇迹般有效。
或者你可以尝试单例模式,例如(只是为了提供想法,你需要根据自己的需要编写代码):
public sealed class Client
{
// A private constructor to restrict the object creation from outside
private Client()
{
...
}
// A private static instance of the same class
private static Client instance = null;
public static Client GetInstance()
{
// create the instance only if the instance is null
if (instance == null)
{
instance = new Client();
}
// Otherwise return the already existing instance
return instance;
}
}
然后你可以打电话给Client.GetInstance();