Pull to refresh

Comments 11

Изменение настроек всех wcf-сервисов (на примере типа привязки)… В app.config сервера изменить все записи в блоке <bindings>*.
В WCF можно описать один биндинг на все сервисы. Почему вы сравниваете грамотную реализацию с неграмотной — и приходите к выводу, что некоторая библиотека лучше?
Я привел последние два примера как раз для иллюстрации того, что не во всех сценариях библиотека позволяет делать меньше действий. Для разделения сервисов на несколько групп с разными настройками конфигурация подходит даже лучше. У нас просто не возникало таких потребностей, поэтому есть только базовые и не всегда удобные механизмы для этого (можно посмотреть реализацию ServiceHostManager или смириться и разделять на уровне контейнеров/проектов).
Это все хорошо до тех пор, пока у вас между сервером и клиентом есть общая сборка контрактов (и желательно — в том же решении, чтобы не развлекаться с переносом кода/сборки); проще говоря — когда у вас у сервиса и клиента единый жизненный цикл. К сожалению, так бывает далеко не всегда (чтобы не сказать «редко»).

(а когда есть гарантированная общая сборка, message-based экономнее)
Я могу только сказать, что у нас совершенно разный опыт разработки под .net. Это касается не только wcf, но и применения EF.
Для типовых приложений, когда сервер и клиент являются по сути одним приложением, описанное мной решение подходит. При этом не важно intranet или internet используется для передачи. Да, в обычном сценарии сборка с OperationContract не добавляется на клиент из-за использования Proxy, туда идёт только DataContract.
Если у сервера и клиента жизненные циклы различаются, они лежат в разных решениях, то можно использовать привлекательный путь web api. Или распространять сборку контрактов через nuget. Или применять классический подход.
Я не пытаюсь сказать, что статья описывает золотой молоток, которого так долго ждали. Для наших задач подходит исходная или немного модифицированная версия библиотеки Rikrop.Core.Wcf. В тоже время я с интересом наблюдаю за библиотекой Boilerplate, которая тоже не является всеобъемлющим решением и, к сожалению, не столь модульна (я бы с удовольствием использовал репозитории и UoF оттуда), но является отличным инструментом для своего круга задач.
>> Для типовых приложений, когда сервер и клиент являются по сути одним приложением, описанное мной решение подходит
Я бы не стал называть это решение типовым. Это один из существующих вариантов (и его распространенность понемногу падает).

>> Да, в обычном сценарии сборка с OperationContract не добавляется на клиент из-за использования Proxy, туда идёт только DataContract.
Туда может вообще ничего не идти, клиент может все создавать на основе метаданных (и иногда это удобно).
И еще — почему у вас в nuget-пакете прописаны зависимости от конкретных версий Unity, а не от диапазонов?
Я приведу цитату из предыдущего поста:
Фиксированная версия Unity. Если в Nuget-пакете для 4.0 не указать версию явно, то nuget попытается зарезолвить последнюю версию, несмотря на то, что она несовместима с .net 4. Если кто-нибудь знает способ избавиться от этой проблемы, просьба сообщить в личку.

Диапазон для 4.0 выставить можно, поскольку известна последняя доступная версия для .net 4.0. Для 4.5 нужно ставить максимальной текущую доступную версию и обновлять по мере выхода новых версий. Возможно, есть другой путь или это лучшее решение?
>> Для 4.5 нужно ставить максимальной текущую доступную версию и обновлять по мере выхода новых версий.
>> Возможно, есть другой путь или это лучшее решение?
Очевидно, есть: указать самую раннюю версию, с которой работает решение, как минимальную, верхнюю границу оставить открытой (или, если вы параноик, зафиксировать мажорную — и только ее — версию).
Привет, Вадим :)

Давай определимся со значением слова «прозрачный» в заголовке статьи.

1. Прозрачный, значит максимально простой для клиента способ получения данных с сервера. Т.е. разработчик Front-end приложения читая код с первого взгляда не может отличить локальный вызов от удаленного.

2. Прозрачный, т.е. максимально простой с точки зрения работы с WCF, те, чтобы человек, читая код, с первого взгляда понял, что к чему.

Они немного противоречат друг другу. Известный нам с тобой фреймворк имеет ряд недостатков, и прозрачностью не обладает, я бы даже сказал, что он слегка громозкий, из-за большого количества классов и абстракций, которые там есть. Человек, который хорошо им владеет, может очень быстро написать клиент-серверное приложение, что прекрасно подходит для небольших проектов, но чтобы эффективно использовать, надо достаточно глубоко в нём разобраться, больше, чем прочитать статью и зареференсить nuget-сборку, иначе в некоторых местах поведение может отличаться от ожидаемого.

Известные проблемы текущей реализации:
1. Фреймворк заточен под хостинг WCF-сервиса в Windows Service или Console Application. Для некоторых решений хостинг в IIS более оптимален, с текущей реализацией фреймворка не сделаешь красивого решения.
2. В текущей реализации фреймворка с WCF-сервиса нельзя вызвать другой WCF-сервис. Эта возможность необходима для некоторых приложений.
3. Текущая реализация работает по net.tcp протоколу, а если необходимо, к примеру, REST API, которое сереализует данные в виде XML/JSON/SOAP?
4. Некоторая реализация WCF-сервисов предоставляет WSDL, что можно использовать так же для автодокументирования сервисов. Здесь этого так же нет.

Подчеркну ещё раз мораль:
Если нужно сделать маленький проект, фреймворк очень хороший.
Если есть желание использовать в продакшне — нужно детально изучить код, прежде, чем класть чужую либо в ядро своего проекта. И лучше исходниками, а не ссылкой на сборку.
Привет, Николай.
Спасибо за комментарий.

Мне нравится прозрачность с точки зрения именно вызова сервисов с клиента — если не брать в рассчет авторизацию, достаточно знать только про то, как пользоваться ServiceExecutor, а с ним напутать сложно.
Что касается эффективного использования и небольших проектов, конкретно эти 2 сборки удалось прикрутить к застарелому приложению на .net 4.0 на Prism с десятком модулей, совсем непростым взаимодействием с wcf и совершенно запутанной работой с сессиями. Это было сделано для быстрого управления конфигурацией и тестов производительности с разными настройками, и с задачей такое решение справилось. То есть, даже в отрыве от остальной инфрастуктуры — работает. Я бы назвал это даже «из коробки».
Стало интересно о реализации вызова wcf-сервисов из других wcf-сервисов, что если добавить клиентскую регистрацию на сервер? Оказалось, что работает:
public class CalculatorService : ICalculatorService
{
    private readonly IServiceExecutor<IAnotherService> _anotherServiceExecutor;

    public CalculatorService(IServiceExecutor<IAnotherService> anotherServiceExecutor)
    {
        _anotherServiceExecutor = anotherServiceExecutor;
    }

    public async Task<int> CalculateSqrSqr(int n)
    {
        return await _anotherServiceExecutor.Execute(service => service.Get(n*n));
    }
}

Я боюсь подумать сейчас о расширенных сценариях, но решение есть. Как и у некоторых других задач, которые могут стать перед пользователем. Я тоже порекомендовал в статье использовать исходный код вместо пакета.
Ещё раз хочу сказать, что сложно пытаться сделать всеохватывающее решение — кому-то из моих коллег хватает простой реализации подобия ServiceExecutor:
var sign = 
        WCFHelper<ISftService>
            .Execute("BasicHttpBinding_ISftService", serviceInstance => serviceInstance.Sign(dataToSign), exception => { });

Мне нравятся идеи сокрытия сложности. Да, иногда для этого нужно написать больше кода, но в конечном счёте какой-нибудь UnitOfWorkAttribute для метода, открывающий и завершающий (если вызывающий метод не был тоже помечен как [UnitOfWork]) или откатывающий при ошибке транзакцию при выходе из метода — того стоит.
Динамическую проксю бы для WebAPI — цены бы такой библиотеке не было.
Т.к. генерация прокси-классов через ручной запуск t4-скриптов — то еще «удовольствие».
Или кто подскажет — может есть уже такая библиотека?
Sign up to leave a comment.

Articles