@Amadan использовал Enumerable # group_by в своем ответе. group_by
и Enumerable#update
(он же merge!
) являются взаимозаменяемыми в том смысле, что когда один из них используется, другой может вместо него использовать обычно strike>. Я покажу, как update
можно использовать здесь.
hashes.each_with_object({}) do |g,h|
h.update(g[:id] => g.merge(source: [g[:source]])) do |_,oh,nh|
oh.merge(source: oh[:source] + nh[:source])
end
end.values
#=> [{:id=>1, :value=>"something", :source=>["a", "b"]},
# {:id=>2, :value=>"something", :source=>["a"]},
# {:id=>3, :value=>"something", :source=>["c"]}]
Во-первых, обратите внимание, что h.update(k=>v)
является сокращением от h.update({ k=>v })
. При этом используется форма Hash # update (он же merge!
), в которой используется блок для определения значений ключей, которые присутствуют в обоих объединяемых хешах. Этот блок имеет три переменные блока: общий ключ (_
), значение обновляемого хеша (oh
, «o» для «старого», «h», потому что значение является хешем) и значение объединяемый хэш (nh
, «n» для «нового»).
Шаги являются следующими.
e = hashes.each_with_object({})
#=> #1, :value=>"something", :source=>"a"},
# {:id=>1, :value=>"something", :source=>"b"},
# {:id=>2, :value=>"something", :source=>"a"},
# {:id=>3, :value=>"something", :source=>"c"}
# ]:each_with_object({})>
Первый элемент этого перечислителя генерируется, передается в блок и присваивается переменным блока.
g,h = e.next
#=> [{:id=>1, :value=>"something", :source=>"a"}, {}]
g #=> {:id=>1, :value=>"something", :source=>"a"}
h #=> {}
Затем выполняется вычисление блока.
h.update(g[:id] => g.merge(source: [g[:source]]))
#=> h.update(1 => g.merge(source: ["a"]))
#=> h.update(1 =>{:id=>1, :value=>"something", :source=>["b"]})
#=> {1=>{:id=>1, :value=>"something", :source=>["b"]}}
До выполнения этого слияния h
было пустым, что означало, что у двух объединяемых хешей не было общих ключей. Поэтому блок разрешения значения update
не был вызван.
Теперь update
направляется [1125] для генерации следующего значения и передачи его в блок. Переменные блока присваиваются этому значению, и выполняется вычисление блока.
g,h = e.next
#=> [{:id=>1, :value=>"something", :source=>"b"},
# {1=>{:id=>1, :value=>"something", :source=>["a"]}}]
g #=> {:id=>1, :value=>"something", :source=>"b"}
h #=> {1=>{:id=>1, :value=>"something", :source=>["a"]}}
Обратите внимание, что h
было обновлено. Теперь вычислите:
h.update(g[:id] => g.merge(source: [g[:source]])) do |_,oh,nh|
oh.merge(source: oh[:source] + nh[:source])
end
#=> {1=>{:id=>1, :value=>"something", :source=>["a", "b"]}}
Как
g[:id]
#=> 1
и
g.merge(source: [g[:source]])
#=> g.merge(source: ["b"])
#=> {:id=>1, :value=>"something", :source=>["b"]}
приведенное выше выражение сокращается до
h.update(1 => {:id=>1, :value=>"something", :source=>["b"]}) do |_,oh,nh|
oh.merge(source: oh[:source] + nh[:source])
end
, так как оба хэша являются объединенные имеют общий ключ 1
, блок вызывается для определения значения 1
в объединенном хэше:
_ = 1
oh = h[1]
#=> {:id=>1, :value=>"something", :source=>["a"]}
nh = g.merge(source: [g[:source]])
#=> g.merge(source: ["b"])
#=> {:id=>1, :value=>"something", :source=>["b"]}
Я использовал подчеркивание (действительное имя локальной переменной) для представляют общий ключ, чтобы сообщить читателю, что он не используется в расчете блока. Блок расчета следующий.
oh.merge(source: oh[:source] + nh[:source])
#=> oh.merge(source: ["a", "b"])
#=> {:id=>1, :value=>"something", :source=>["a", "b"]}
Расчеты аналогичны для остальных элементов, сгенерированных e
. Таким образом, мы получаем:
f = hashes.each_with_object({}) do |g,h|
h.update(g[:id] => g.merge(source: [g[:source]])) do |_,oh,nh|
oh.merge(source: oh[:source] + nh[:source])
end
end
#=> {1=>{:id=>1, :value=>"something", :source=>["a", "b"]},
# 2=>{:id=>2, :value=>"something", :source=>["a"]},
# 3=>{:id=>3, :value=>"something", :source=>["c"]}}
Последний шаг - возврат f.values
.
Определите пространства имен с Сериализацией XML (или, лучше) атрибуты определения Контракта Данных.
например, с Сериализацией XML:
[Serializable, XmlRoot(namespace="http://example.com/eg1")]
public class MyClass {
[XmlElement(ElementName = "DataString")]
public string MyString { get; set; }
}
например, с сериализацией Контракта Данных:
[DataContract(Namespace="http://example.com/eg2")]
public class MyClass {
[DataMember]
public string MyString { get; set; }
}
Править
На основе первого комментария не будет работать вышеупомянутое, потому что требование состоит в том, чтобы установить пространство имен на обертке SOAP вокруг сообщения, не на самом сообщении.
OperationContractAttribute
предложения никакое управление пространств имен, и я не вижу никаких других атрибутов WCF на уровне метода.
Две возможности: (1) Можно иметь достаточно контроля путем отбрасывания уровня абстракции и использования сообщения Контракт. (2) Получите текущий WSDL для сервиса (использование svcutil.exe
), вручную корректируя его для получения пространств имен Вы хотите, и затем использование svcutil.exe
снова сгенерировать код и посмотреть на получающийся код.