Использование ссылок DLL службы WCF в другой службе WCF

Извините за длинный вопрос в первую очередь. Я бы предпочел задать более короткий вопрос, но это самая урезанная версия, которую я могу предоставить, чтобы я мог четко объяснить свою точку зрения.

Я пытался предоставить нашему клиенту услугу-оболочку, которая должна предоставлять в нем несколько услуг. Идея заключается в том, чтобы сократить несколько вызовов до одного вызова и вернуть один объект, в котором есть другие связанные объекты. Чтобы проиллюстрировать мою точку зрения, позвольте мне привести следующий пример:

Допустим, у нас есть следующие услуги:

  • Моя Компания.Услуги.Пожертвование
  • Моя Компания.Услуги.Оплата
  • МояКомпания.Услуги.Частичная Оплата

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

Вместо того, чтобы клиент делал это, я собираюсь предоставить службу-оболочку, которая принимает donationID в качестве единственного параметра и возвращает класс, подобный этому:

[DataContract(Namespace = "http://MyCompany.Services.DonationDetail")]
public class DonationDetail
{
     [DataMember]
     public MyCompany.Services.Donation.Record donationRecord;
     [DataMember]
     public PaymentDetail paymentDetail;    
}

[DataContract(Namespace = "http://MyCompany.Services.DonationDetail")]
public class PaymentDetail
{
     [DataMember]
     public MyCompany.Services.Payment.Record paymentRecord;
     [DataMember]
     public List<MyCompany.Services.PartialPayment.Record> partialPayments;
}

Таким образом, экземпляр записи DonationDetail должен возвращать всю соответствующую информацию об этом пожертвовании.

Моя проблема возникает, когда я использую DLL этих отдельных служб * в своей службе-оболочке, поскольку любой класс, который я передаю клиенту с помощью службы-оболочки, становится частью службы-оболочки, и клиент не может сразу использовать их с соответствующими типами, которые они извлекли, используя ссылки на службы без написание пользовательского метода построения для преобразования одного типа в другой, хотя это одни и те же объекты. Вместо того, чтобы ссылаться на классы в исходном пространстве имен, сервис теперь использует следующие классы, что-то вроде этого для классов, упомянутых выше:

  • DonationDetail.Record (Запись о пожертвовании - я бы ожидал MyCompany.Services.Donation.Record)
  • DonationDetail.Record1 (Запись платежа - я бы ожидал MyCompany.Services.Payment .Record)
  • DonationDetail.Record2 (Запись PartialPayment — я бы ожидал MyCompany.Services.PartialPayment.Record)

Есть ли способ предоставить такой интерфейс без специального конструктора? Итак, если они используют пространство имен «PartialPayment» для службы WCF MyCompany.Services.PartialPayment, могут ли они сделать что-то ниже после получения DonationDetail через службу-оболочку?

PartialPayment.Record partialPayment = dDetailObj.paymentDetail.partialPayments[0];

*: Не спрашивайте меня, почему я не использую ссылки на сервисы, если это не является причиной проблемы, так как этот вариант создает для меня другие проблемы на данный момент)


person Ferhat    schedule 06.04.2012    source источник


Ответы (1)


Итак, я думаю, что вы, по сути, говорите, что если у вас есть две разные службы, которые возвращают один и тот же объект, и когда вы добавляете это как две разные ссылки на службу для клиента, даже если в конечном итоге они являются одним и тем же объектом, что касается служб (поскольку они ссылаются на одну и ту же DLL), клиент видит их как два разных типа, поэтому вы не можете взять объект, возвращенный из одного, и отправить его в качестве входных данных для другой службы.

Предполагая, что я понял ваш вопрос (и я извиняюсь, если я не понял)...

Вы можете сопоставить один тип с другим, создав его и установив свойства, но это действительно досадно и не очень удобно для потребителя и т. д., поэтому я собираюсь предложить нечто радикальное. ..

Удалите ссылки на службы на клиенте.

Ага, я же сказал, зачем мне такое предлагать!?! Вот почему...

Прежде всего, я бы убедился, что мой проект структурирован примерно так:

Клиентская библиотека сведений о пожертвованиях

  • IDonationService (это сервисный контракт — обратите внимание на отсутствие реализации в клиентской библиотеке)
  • ПожертвованиеRecord

Клиентская библиотека сведений о платежах

  • IPaymentService (это сервисный контракт — обратите внимание, что в клиентской библиотеке нет реализации)
  • Платежная запись

Клиентская библиотека частичной оплаты

  • IPartialPaymentService (это сервисный контракт — обратите внимание, что в клиентской библиотеке нет реализации)
  • Запись частичной оплаты

Клиентская библиотека Wrapper Service (которая ссылается на три другие клиентские библиотеки)

  • IWrapperService (это сервисный контракт — обратите внимание на отсутствие реализации в клиентской библиотеке)

Между прочим, я дал вашим записям разные имена классов, но вы можете использовать пространства имен, если хотите, и называть их все Записями (я думаю, называть их разными именами менее запутанно, но, вероятно, это только мое мнение).

На стороне службы вы ссылаетесь на клиентскую библиотеку, необходимую для реализации службы, и делаете все, что вам нужно, как всегда.

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

Затем у клиента есть интерфейс для контракта службы и всех контрактов данных, поэтому ему не нужна вся ссылка на службу, сгенерированный код. Вместо этого вы можете сделать на своем клиенте что-то вроде этого:

DonationRecord donation;

using (var cf = new ChannelFactory<IDonationService>("EndpointNameInConfigurationFile"))
{
    IDonationService donationservice = cf.CreateChannel();
    donation = donationservice.GetDonation("Donation1234");
}

using (var cf = new ChannelFactory<IWrapperService>("EndpointNameInConfigurationFile"))
{
    IWrapperService wrapperService = cf.CreateChannel();
    wrapperService.DoSomethingWithDonation(donation);
}

Вот видите, я взял контракт данных из одного сервиса и отправил его в совершенно не связанный с ним сервис, и это выглядит естественно (у меня есть объект, который возвращается из метода в классе X, и я взял его и передал как аргумент в классе Y, работа сделана, как программирование).

ПРИМЕЧАНИЕ. Использование этого метода не помешает ссылкам на службы работать так, как они всегда работали, поэтому любой существующий клиентский код не должен изменяться, просто если вы используете новую службу-оболочку, вы можете использовать ее следующим образом. чтобы сэкономить на картах типов.

person kmp    schedule 06.04.2012
comment
Привет, кмп, я отвечу на ваш ответ, но работа, которую я имею, заставляет меня откладывать, так как я хочу уточнить некоторые из ваших предложений и опробовать их, прежде чем делать это. Я хотел поблагодарить вас за то, что уделили мне время. - person Ferhat; 11.04.2012