Один из вариантов - использовать статические элементы, как сказал Джимми Макналти. У меня есть служба 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() происходит в его собственном экземпляре службы, и каждый экземпляр имеет доступ к статической коллекции. Поскольку каждый экземпляр службы работает в отдельном потоке, доступ к коллекции должен быть синхронизирован.
Как и вся синхронизация, выполняемая в многопоточном программировании, не забудьте минимизировать время, затрачиваемое на блокировку. В показанном примере, как только первый вызывающий абонент захватывает блокировку, все остальные вызывающие абоненты должны ждать, пока блокировка не будет отпущена. Это работает в моей ситуации, но может не работать в вашей.
Другим вариантом является использование режима экземпляра Single service, в отличие от режима экземпляра службы PerCall.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService : IMyService
{ ... }
Из всего, что я прочитал, PerCall кажется более гибким.
Вы можете следить за этим link за отличия между ними.
И не забывайте, что класс, который реализует ваш сервис, - это просто класс. Он работает, как и все классы C#. Вы можете добавить статический конструктор, свойства, обработчики событий, реализовать дополнительные интерфейсы и т. Д.