Yes, you can absolutely do that.
The easiest way is to implement your service as a PerSession service, and capture the callback context on initialization/construction. Typically I will add the service object (which really represents a connection at that point) to an internal core object.
Then, when you get in a message from a client, you can make a call to any of the service objects (not through the contract), and internally forward the data to the associated client.
This is a pretty minimal implementation of the concept, without exception handling, and some pretty bad design (static class BAD!). I haven't tested this, but the principles should hold even if I missed crossing an i or dotting a t. This example also forwards the calls to all clients, but selecting an individual client follows the same basic pattern.
Trying to do this with a singleton service will be more difficult, and a per-call service obviously won't work :)
[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IContract
{
[OperationContract(IsOneWay = true)]
void SendTheData(string s);
}
public interface ICallback
{
[OperationContract(IsOneWay = true)]
void ForwardTheData(string s);
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.PerSession)]
public class ServiceConnection : IContract
{
private ICallback m_callback;
public ServiceConnection()
{
m_callback = OperationContext.Current.GetCallbackChannel<ICallback>();
ServiceCore.Add(this);
}
public void SendTheData(string s)
{
ServiceCore.DataArrived(s);
}
public void SendToClient(string s)
{
m_callback.ForwardTheData(s);
}
}
static public class ServiceCore
{
static private List<ServiceConnection> m_connections = new List<ServiceConnection>();
public static void DataArrived(string s)
{
foreach(ServiceConnection conn in m_connections)
{
conn.SendTheData(s);
}
}
public static void Add(ServiceConnection connection)
{
m_connections.Add(connection);
}
}