Один из вариантов - использовать статические члены, как сказал Джимми МакНалти. У меня есть служба WCF, которая открывает сетевые подключения на основе указанного пользователем IP-адреса. Мой сервис настроен на режим экземпляра сервиса PerCall. В каждом сеансе я проверяю статическую структуру данных, чтобы увидеть, открыто ли сетевое соединение для указанного IP-адреса. Вот пример.
[ServiceContract]
public interface IMyService
{
[OperationContract]
void Start(IPAddress address);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class MyService : IMyService
{
private static readonly List<IPAddress> _addresses = new List<IPAddress>();
public void Start(IPAddress address)
{
lock(((ICollection)_addresses).SyncRoot)
{
if (!_addresses.Contains(address)
{
// Open the connection here and then store the address.
_addresses.Add(address);
}
}
}
}
Как настроено, каждый вызов Start () происходит внутри своего собственного экземпляра службы, и каждый экземпляр имеет доступ к статической коллекции. Поскольку каждый экземпляр службы работает в отдельном потоке, доступ к коллекции должен быть синхронизирован.
Как и во всей синхронизации, выполняемой в многопоточном программировании, обязательно минимизируйте время, затрачиваемое на блокировку. В показанном примере, как только первый абонент захватывает блокировку, все остальные абоненты должны ждать, пока блокировка не будет снята. Это работает в моей ситуации, но может не работать в вашей.
Другой вариант - использовать режим экземпляра единой службы, а не режим экземпляра службы PerCall.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService : IMyService
{ ... }
Однако из всего, что я прочитал, PerCall выглядит более гибким.
Вы можете перейти по этой ссылке для различий между ними.
И не забывайте, что класс, который реализует ваш сервис, это просто класс. Это работает как все классы C #. Вы можете добавить статический конструктор, свойства, обработчики событий, реализовать дополнительные интерфейсы и т. Д.