WCF определяет свою собственную версию объекта DataObject в справочнике услуг.

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

Объект используется в качестве параметра функции в контракте на обслуживание.

    [OperationContract(IsOneWay = true)]
    void UpdateInformation(MyObject myObject);

Ошибка, которую я получаю при попытке вызвать функцию из моего клиента, это "Аргумент 1: невозможно преобразовать из" MyNameSpaceDTO.MyObject "в" MyNameSpace.ServiceReference1.MyObject ""

Объект находится в собственной библиотеке классов DLL и помечен атрибутами [DataObject] и [DataMember].

namespace MyNameSpaceDTO
{
    [DataContract]
    public class MyObject
    {
        [DataMember]
        public string Name { get; set; }
    ….

Но также заканчивается в Reference.cs после добавления ссылки на сервис как:

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="MyObject", Namespace="http://schemas.datacontract.org/2004/07/MyNameSpaceDTO")]
[System.SerializableAttribute()]
public partial class MyObject : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {

    [System.NonSerializedAttribute()]
    private System.Runtime.Serialization.ExtensionDataObject extensionDataField;

    [System.Runtime.Serialization.OptionalFieldAttribute()]
    private string NameField;
    ...

Кроме того, у меня есть следующий набор в разделе "Дополнительно" справочника по добавлению услуг:

[x] Повторное использование типов в ссылочных сборках

(o) Повторное использование типов во всех ссылочных сборках

1 ответ

Решение

Для использования службы WCF вы часто видите примеры (и они, несомненно, желательны!), Где вам предлагают добавить эту службу через диалоговое окно " Добавить ссылку на службу ". Путем ссылки на сервис таким образом ваше клиентское приложение создает прокси-классы из WSDL, предоставляемого сервисом.

В результате вы получаете, например, класс MyNameSpaceDTO.MyObject в вашем контракте-сборка и MyNameSpace.ServiceReference1.MyObject в вашем клиентском приложении, сгенерированном из WSDL. Это может показаться несколько излишним.

Такое поведение может потребоваться в следующих случаях: представьте, что вы хотите использовать произвольный общедоступный веб-сервис, который вы не контролируете. У вас нет доступа к контрактной сборке, которая определяет типы и т. Д. В этой ситуации создание собственных локальных прокси-классов из предоставляемого WSDL является оптимальным, поскольку это ваш единственный способ получить необходимые типы и так далее.

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

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

Пожалуйста, посмотрите на этот пример:

РЕДАКТИРОВАТЬ:

Пожалуйста, обратите внимание на некоторые изменения: наиболее важным является то, что вы обычно не захотите делиться сборкой, которая содержит логику реализации вашего сервиса. Поэтому я извлек эту часть из Контракт-сборки и поместил в отдельную Реализацию-сборку. При этом вы просто делитесь интерфейсами и типами, а не логикой реализации. Это изменение также отражено на скриншоте выше.

Вы можете настроить это маленькое решение с помощью следующих классов:

Контракт - IService1.cs:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    string GetData(int value);
}

Реализация - Service1.cs:

public class Service1 : IService1
{
    public string GetData(int value)
    {
        return string.Format("You entered: {0}", value);
    }
}

Хост - Program.cs:

class Program
{
    static void Main(string[] args)
    {
        var baseAddress = new Uri("http://localhost:8732/Design_Time_Addresses/Service1/");

        using (var host = new ServiceHost(typeof(Service1), baseAddress))
        {
            // Enable metadata publishing.
            var smb = new ServiceMetadataBehavior();
            smb.HttpGetEnabled = true;
            smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
            host.Description.Behaviors.Add(smb);

            // Open the ServiceHost to start listening for messages. Since no endpoints are
            // explicitly configured, the runtime will create one endpoint per base address
            // for each service contract implemented by the service.
            host.Open();

            Console.WriteLine("The service is ready at {0}", baseAddress);
            Console.WriteLine("Press <Enter> to stop the service.");
            Console.ReadLine();

            host.Close();
        }
    }
}

Клиент - Program.cs:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Press <Enter> to proceed.");
        Console.ReadLine();

        var binding = new BasicHttpBinding();
        var endpoint = new EndpointAddress("http://localhost:8732/Design_Time_Addresses/Service1/");
        var channelFactory = new ChannelFactory<IService1>(binding, endpoint);

        // Create a channel.
        IService1 wcfClient1 = channelFactory.CreateChannel();
        string s = wcfClient1.GetData(42);
        Console.WriteLine(s);
        ((IClientChannel)wcfClient1).Close();

        Console.WriteLine("Press <Enter> to quit the client.");
        Console.ReadLine();
    }
}
Другие вопросы по тегам