Доска рекордов на WCF и RavenDB. Сервис
Несколько раз на работе делали миниигры — пасхалки на новый год или еще какой праздник. Каждый раз единственное, что не успевали — таблица рекордов. Ее и буду делать. Доска будет представлять собой сервис с 2 методами — добавить результат и получить топ n результатов.
Для начала создадим интерфейс сервиса — контракт в терминах WCF
/// <summary>
/// Контракт сервиса доски рекордов.
/// </summary>
[ServiceContract]
public interface IScoreBoard
{
/// <summary>
/// Получить список лучших результатов.
/// </summary>
/// <param name="count">Количество результатов.</param>
/// <returns>Список лучших результатов.</returns>
[OperationContract]
List<ScoreBoardResult> GetTopResults(int count);
/// <summary>
/// Добавить результат.
/// </summary>
/// <param name="result">Результат.</param>
[OperationContract]
void AddResult(ScoreBoardResult result);
}
и класс, в котором будут храниться результаты
/// <summary>
/// Результат в таблице рекордов.
/// </summary>
[DataContract]
public class ScoreBoardResult
{
/// <summary>
/// Игра.
/// </summary>
[DataMember]
public string Game { get; set; }
/// <summary>
/// Код пользователя.
/// </summary>
[DataMember]
public string UserCode { get; set; }
/// <summary>
/// Имя пользователя.
/// </summary>
[DataMember]
public string UserName { get; set; }
/// <summary>
/// Набранные очки.
/// </summary>
[DataMember]
public int Score { get; set; }
}
Подробнее об атрибутах:
ServiceContract — атрибут контракта сервиса. Это интерфейс, по которому можно работать с сервисом.
OperationContract — метод интерфейса сервиса.
DataContract — данные, которые передаются между клиентом и сервером.
DataMember — свойство, которое передается при передаче класса, помеченного DataContract.
Теперь добавляем в конфиг приложения такой кусок:
<system.serviceModel>
<services>
<service name="ScoreBoardServer.ScoreBoardService"
behaviorConfiguration="returnFaults">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9875"/>
</baseAddresses>
</host>
<endpoint address="net.tcp://localhost:9876/"
binding="netTcpBinding"
contract="ScoreBoardServer.IScoreBoard" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="returnFaults">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Осталось только добавить класс с реализацией самого сервиса:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] internal class ScoreBoardService : IScoreBoard
Здесь InstanceContextMode.Single означает, что все запросы клиентов будет обрабатывать один и тот же экземпляр сервиса.
При старте приложения сервис запускается так:
using (var serviceHost =
new ServiceHost(typeof(ScoreBoardService)))
{
serviceHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.ReadLine();
serviceHost.Close();
}
Теперь, если открыть http://localhost:9875, то появится сообщение о том, что сервис успешно запущен. Можно приступать к клиенту и хранению данных. Об этом во второй части.
