Как в общем случае выполнить сервисные операции в WCF? - PullRequest
2 голосов
/ 10 января 2010

Я ищу способ реализовать поведение, показанное в исходном коде ниже. Я создал прокси службы WCF с опцией «Всегда создавать контракты сообщений». Все мои контракты с запросами и ответными сообщениями реализуют общий интерфейс, и я хотел бы выполнить их, используя одну и ту же функцию. Мне кажется, что должен быть общий способ отправки сообщений через клиентский прокси, но я нигде не могу его найти. Любая помощь будет принята с благодарностью!

// I can do this
private IPagedResponse GetAllFoods()
{
    NutrientDBClient client = new NutrientDBClient();
    GetAllFoodsRequest request = new GetAllFoodsRequest();
    GetAllFoodsResponse response = client.GetAllFoods(request);

    return response;
}
// I'd like to do this
private IPagedResponse ExecutePagedRequest(IPagedRequest request)
{
    NutrientDBClient client = new NutrientDBClient();
    IPagedResponse response = (IPagedResponse)client.Execute(request);

    return response;
}

В настоящее время я добавил метод ExecutePagedRequest (IPagedRequest) в NutrientDBClient и вручную выполнил правильную операцию службы на основе конкретного типа IPagedRequest. Я ищу более элегантный способ, чтобы я мог просто реализовать IPagedRequest в контракте сообщений, и он автоматически работает.

Ответы [ 2 ]

2 голосов
/ 11 января 2010

Не уверен на 100%, чего вы действительно хотите достичь, но позвольте мне объяснить несколько основ о WCF.

Многие программисты ошибочно считают WCF своего рода удаленным удалением .NET, например они полагают, что вы в основном обращаетесь к удаленному объекту на удаленном сервере, вызывая метод для «удаленного» объекта .NET. Это абсолютно не тот случай!

WCF - это примерно обмен сообщениями - ваш клиент и сервер обмениваются только сериализованными сообщениями (и, возможно, заголовками) - но это все.

Тем не менее: эти механизмы обмена сообщениями предназначены для взаимодействия со многими платформами, отличными от .NET - Java, Ruby - вы называете это. Они используют механизмы WSDL и XSD для обмена описаниями операций (WSDL) и структурами данных, которыми обмениваются (XSD).

WSDL и XSD - все о четко определенных, явных вызовах и структурах данных. Функциональность, предлагаемая этими стандартами, является наименьшим общим знаменателем среди всех платформ SOA - и, как таковая, она немного более ограничена, чем то, что вы, возможно, привыкли к использованию чистого .NET. Мир SOA и мир ООП не всегда совпадают.

Итак, в конце концов, то, что вам действительно нужно понять и запрограммировать, - это стандарты, определенные WSDL / XSD, и поэтому вы должны забыть обо всех тонкостях .NET, таких как обобщенные элементы, интерфейсы и классы, реализующие эти интерфейсы очень быстро Они просто не работают над инфраструктурой обмена сообщениями WCF.

Все, что вы можете обменять между клиентом WCF и сервером WCF, - это все, что вы можете описать и выразить в схеме XML - конкретные типы, состоящие из базовых типов данных, таких как строки, целые числа и т. Д. XSD поддерживает некоторую часть наследования, но не знает приседаний о дженериках и вообще не имеет дело с интерфейсами и неконкретными классами.

Итак, я не думаю, что ваш подход с универсальным интерфейсом и сообщениями, реализующими этот интерфейс, и WCF, выясняющий, какой реальный метод вызывать на основе этого класса, сработает. Это просто не то, как WCF был спроектирован и предназначен для работы.

Возможно, вам удастся создать собственный (но конкретный) базовый класс, и вы сможете расширить диспетчер операций WCF на стороне сервера для вызова различных методов на основе передаваемых классов (или некоторой дополнительной информации в заголовки, идущие вместе для поездки) - но я не думаю, что это будет легко, и на самом деле способ, которым WCF предназначен для работы - нет никаких гарантий, что вы действительно сможете его осуществить.

0 голосов
/ 11 января 2010

Ниже показано, как я решил эту проблему. Мои сообщения заключают контракты, реализуют IPagedRequest и IPagedResponse. NutrientDBClient - это мой клиентский прокси, сгенерированный кодом (ClientBase). ExecutePagedRequest () выполняет маршрутизацию сообщений на основе конкретного типа запроса.

public interface IPagedRequest
{
    PagingContext PageInfoState { get; set; }
}

public interface IPagedResponse
{
    PagingContext PageInfoState { get; }
    IEnumerable ResultItems { get; }
}

public partial class NutrientDBClient : IHasPagedServiceOperations
{
    public IPagedResponse ExecutePagedRequest(IPagedRequest request)
    {
        if (request == null) { throw new ArgumentNullException("request"); }

        if (typeof(GetAllFoodsRequest).IsAssignableFrom(request.GetType()))
        {
            return GetAllFoods((GetAllFoodsRequest)request);
        }

        // Other Service Operations that take IPagedRequest and 
        // return IPagedResponse removed for example


        throw new NotSupportedException(
            string.Format("Paged requests of type {0} are not supported.",
                request.GetType().Name));
    }
}
...