Могу ли я остановить мой WCF, генерирующий ArrayOfString вместо строки [] или List <string>
У меня есть небольшая проблема с прокси-серверами 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>
-, который соответствует моему исходному объекту С# выше.
[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
- не удается выполнить "неактивный", даже если он компилирует только тонкие
- create
new ArrayOfString()
, а затем AddRange(unsubscribeFrom.ToList())
- работает, но я не могу сделать все это в одном выражении
- создайте функцию преобразования
ToArrayOfString(List<string>)
, которая работает, но не так чиста, как я хочу.
Он делает это только для строки, что раздражает.
Мне что-то не хватает? Есть ли способ сказать ему не генерировать ArrayOfString
- или какой-нибудь другой трюк, чтобы назначить его?
Ответы
Ответ 1
Любой объект .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>()
});
Ответ 2
Я предпочитаю не возвращать общие типы через границу сервиса в первую очередь. Вместо этого верните Unsubscribe как string[]
и SubscriptionInfo как SubscriptionInfo[]
. При необходимости массив можно легко преобразовать в общий список на клиенте, как показано ниже:
Unsubscribe = new List<string>(unsubscribeFrom);
Subscribe = new List<SubscriptionInfo>(subscribeTo);
Ответ 3
Слишком поздно, но может помочь людям в будущем...
Использовать 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 ok?!
Ответ 4
Если вы используете VS 2008 для потребления услуг, тогда есть простое решение.
Нажмите кнопку "Дополнительно..." в диалоговом окне прокси-сервера, которое отображается при добавлении сервисной ссылки. В раскрывающемся списке Тип коллекции вы можете выбрать System.Generic.List. Теперь возвращаемые методы должны работать правильно.
(Надеюсь, это то, о чем вы просили, я немного устал, и вопрос был для меня трудным для чтения.)