Я самостоятельно размещаю службу WCF и желаю, чтобы мой объект службы был единичным.Мой клиент использует канал для доступа к сервису.Хост и клиент являются консольными приложениями и перечислены ниже.
У моей службы есть метод, который возвращает интерфейс внутреннему объекту.Этот внутренний объект содержит методы для получения / установки числа.Мой сервис имеет альтернативные методы для получения / установки номера этого внутреннего объекта.
Моя проблема заключается в том, что установка номера внутреннего объекта через интерфейс, возвращаемый службой, и установка его с помощью метода службы (SetInternalNumber), по-видимому, не устанавливают один и тот же объект.Когда я получаю значения, они разные.
Мое клиентское приложение показывает начальный номер внутреннего объекта, изменяя этот номер, получая другой интерфейс к объекту и его начальное значение, устанавливая значение через службу и перечисляяразличные значения.
Я думал, что было создано несколько экземпляров моего внутреннего объекта, но это не так.Я знаю это, потому что напечатал строку в конструкторе объектов и вижу эту строку только один раз.
Что происходит?Я подумал, что, возможно, Внутренний класс должен быть помечен как одиночный (InstanceContextMde.Single), но это не сработало.
Интерфейс службы
[ServiceContract]
public interface IMyService
{
[OperationContract]
[ServiceKnownType(typeof(Internal))]
IInternal GetMyInterface();
[OperationContract]
int GetInternalNumber();
[OperationContract]
void SetInternalNumber(int number);
}
Реализация службы
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyService : IMyService
{
private IInternal _internal;
public MyService()
{
Random rng = new Random();
_internal = new Internal(rng.Next());
}
public int GetInternalNumber()
{
return _internal.GetNumber();
}
public IInternal GetMyInterface()
{
return _internal;
}
public void SetInternalNumber(int number)
{
_internal.SetNumber(number);
}
}
Внутренний интерфейс объекта
[ServiceContract]
public interface IInternal
{
[OperationContract]
int GetNumber();
[OperationContract]
void SetNumber(int number);
}
Внутренняя реализация объекта
[DataContract]
public class Internal : IInternal
{
[DataMember]
private int _number;
public Internal(int number)
{
_number = number;
Console.WriteLine($"creating Internal - {_number}");
}
public int GetNumber()
{
return _number;
}
public void SetNumber(int number)
{
_number = number;
}
}
Самостоятельное приложение
static void Main(string[] args)
{
Uri baseAddress = new Uri(@"http://localhost:12345/GettingStarted");
MyService singleton = new MyService();
ServiceHost selfHost = new ServiceHost(singleton, baseAddress);
try
{
selfHost.AddServiceEndpoint(typeof(IMyService), new BasicHttpBinding(), "MyService");
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
selfHost.Description.Behaviors.Add(smb);
selfHost.Open();
Console.WriteLine("host is open");
Console.ReadLine();
selfHost.Close();
}
catch (Exception ex)
{
Console.WriteLine($"exception: {ex.Message}");
Console.ReadLine();
selfHost.Abort();
}
}
Клиентское приложение
static void Main(string[] args)
{
var myBinding = new BasicHttpBinding();
var myEndpoint = new EndpointAddress(@"http://localhost:12345/GettingStarted/MyService");
using (var myChannelFactory = new ChannelFactory<IMyService>(myBinding, myEndpoint))
{
IMyService service = null;
try
{
service = myChannelFactory.CreateChannel();
Console.WriteLine("channel created");
// get interface to concrete object
IInternal myInternal = service.GetMyInterface();
Console.WriteLine($"initial number = {myInternal.GetNumber()}");
Console.ReadLine();
// set a new # with Internal interface
Console.WriteLine("set new number");
myInternal.SetNumber(123);
Console.WriteLine($"new number = {myInternal.GetNumber()}");
Console.ReadLine();
// get another interface, don't set its number
Console.WriteLine("get another interface, initial value");
IInternal anotherInternal = service.GetMyInterface();
Console.WriteLine($"number(another) = {anotherInternal.GetNumber()}");
Console.ReadLine();
// set # with service
Console.WriteLine("set # through server");
service.SetInternalNumber(789);
// what are the #s?
Console.WriteLine();
Console.WriteLine($"from Internal: {myInternal.GetNumber()}");
Console.WriteLine($"from another Internal = {anotherInternal.GetNumber()}");
Console.WriteLine($"from service = {service.GetInternalNumber()}");
Console.ReadLine();
((ICommunicationObject)service).Close();
myChannelFactory.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.ReadLine();
(service as ICommunicationObject)?.Abort();
}
}
}