Могу ли я остановить свой WCF, генерирующий ArrayOfString вместо string [] или List <string> - PullRequest
12 голосов
/ 03 февраля 2009

У меня небольшая проблема с прокси-серверами WCF, где сообщение содержит List<string> в качестве параметра.

Я использую «Добавить ссылку на службу» в Visual Studio, чтобы сгенерировать ссылку на мою службу.

   // portion of my web service message
   public List<SubscribeInfo> Subscribe { get; set; }
   public List<string> Unsubscribe { get; set; }

Это сгенерированные свойства моего MsgIn для одного из моих веб-методов. Вы можете видеть, что он использовал ArrayOfString, когда я использую List<string>, а другой принимает List<SubscribeInfo> - что соответствует моему исходному объекту C # выше.

[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
public System.Collections.Generic.List<DataAccess.MailingListWSReference.SubscribeInfo> Subscribe {
    get {
        return this.SubscribeField;
    }
    set {
        if ((object.ReferenceEquals(this.SubscribeField, value) != true)) {
            this.SubscribeField = value;
            this.RaisePropertyChanged("Subscribe");
        }
    }
}

[System.Runtime.Serialization.DataMemberAttribute(EmitDefaultValue=false)]
publicDataAccess.MailingListWSReference.ArrayOfString Unsubscribe {
    get {
        return this.UnsubscribeField;
    }
    set {
        if ((object.ReferenceEquals(this.UnsubscribeField, value) != true)) {
            this.UnsubscribeField = value;
            this.RaisePropertyChanged("Unsubscribe");
        }
    }
}

Созданный класс ArrayOfString выглядит следующим образом. Это класс, сгенерированный в моем коде - это не класс .NET. Это фактически породило у меня класс, который наследуется от List, но у него не было «порядочности», чтобы создавать мне конструкторы.

    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]
    [System.Runtime.Serialization.CollectionDataContractAttribute(Name="ArrayOfString", Namespace="http://www.example.com/", ItemName="string")]
    [System.SerializableAttribute()]
    public class ArrayOfString : System.Collections.Generic.List<string> {
    }

Проблема в том, что я часто создаю свое сообщение так:

client.UpdateMailingList(new UpdateMailingListMsgIn()
{
    Email = model.Email,
    Name = model.Name,
    Source = Request.Url.ToString(),
    Subscribe = subscribeTo.ToList(),
    Unsubscribe = unsubscribeFrom.ToList()
});

Мне действительно нравится чистый внешний вид, который это дает мне.

Теперь для актуальной проблемы:

Я не могу присвоить List<string> свойству Unsubscribe, которое является ArrayOfString - даже если оно наследуется от List. На самом деле, я не могу найти ЛЮБОЙ способ присвоить его без дополнительных утверждений.

Я пробовал следующее:

  • new ArrayOfString(unsubscribeFrom.ToList()) - этот конструктор не существует: - (
  • изменение типа массива, используемого генератором кода - не работает - оно всегда дает мне ArrayOfString (!?)
  • попытаться привести List<string> к ArrayOfString - не удается выполнить «невозможно выполнить», даже если он компилируется очень хорошо
  • создать new ArrayOfString(), а затем AddRange(unsubscribeFrom.ToList()) - работает, но я не могу сделать все это в одном утверждении
  • создать функцию преобразования ToArrayOfString(List<string>), которая работает, но не так чиста, как я хочу.

Это только делает для строки, что раздражает.

Я что-то упустил? Есть ли способ сказать ему не генерировать ArrayOfString - или какой-то другой трюк, чтобы назначить его?

Ответы [ 4 ]

7 голосов
/ 12 марта 2010

Любой объект .NET, который реализует метод с именем «Добавить», может быть инициализирован так же, как массивы или словари.

Поскольку ArrayOfString реализует метод «Добавить», вы можете инициализировать его следующим образом:

var a = new ArrayOfString { "string one", "string two" };

Но, если вы действительно хотите инициализировать его на основе другой коллекции, вы можете написать метод расширения для этого:

public static class U
{
    public static T To<T>(this IEnumerable<string> strings)
        where T : IList<string>, new()
    {
        var newList = new T();
        foreach (var s in strings)
            newList.Add(s);
        return newList;
    }
}

Использование:

client.UpdateMailingList(new UpdateMailingListMsgIn()
{
    Email = model.Email,
    Name = model.Name,
    Source = Request.Url.ToString(),
    Subscribe = subscribeTo.ToList(),
    Unsubscribe = unsubscribeFrom.To<ArrayOfString>()
});
3 голосов
/ 20 апреля 2011

Слишком поздно, но может помочь людям в будущем ...

Используйте svcutil и явным образом сообщите утилите командной строки, что вы хотите, чтобы прокси-класс сериализовался XmlSerializer , а не DataContractSerializer (по умолчанию). Вот образец:

svcutil /out:c:\Path\Proxy.cs /config:c:\Path\Proxy.config / async / serializer: XmlSerializer / namespace: *, YourNamespace http://www.domain.com/service/serviceURL.asmx

Обратите внимание, что веб-сервис является веб-сервисом ASP.NET ок?!

3 голосов
/ 06 марта 2009

Я предпочитаю не возвращать универсальные типы через границу службы. Вместо этого верните Unsubscribe как string[] и SubscriptionInfo как SubscriptionInfo[]. При необходимости массив можно легко преобразовать в общий список на клиенте следующим образом:

Unsubscribe = new List<string>(unsubscribeFrom);
Subscribe = new List<SubscriptionInfo>(subscribeTo);
1 голос
/ 03 февраля 2009

Если вы используете VS 2008 для обслуживания, есть простое решение.

Нажмите кнопку «Дополнительно ...» в диалоговом окне прокси, которое отображается при добавлении ссылки на службу. В раскрывающемся списке Тип коллекции вы можете выбрать System.Generic.List. Методы, возвращающие List, теперь должны работать правильно.

(Надеюсь, это то, о чем вы просили, я немного устала, и мне было трудно прочитать этот вопрос.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...