2016-03-02 67 views
2

我爲我的WCF服務實現了一個自定義的DataContractResolver,它使用已知的類型列表並按名稱查找它們。在大多數情況下,它可以工作(包括通用數組,例如「ArrayOfMyClass」)。但是,對於其他通用類型,在ResolveName()的參數typeName的末尾會附加一個看似隨機的八個字符的字符串。在這個例子中該字符串是AevzrKY9:在第1行位置奇怪的字符串附加到DataContractResolver.ResolveName中的typeName作爲泛型類型

錯誤345.元素'http://services.contoso.com/QueryService:QueryResult'包含來自映射到名稱「http://schemas.datacontract.org/2004/07/Contoso.Services.Contract.Infrastructure:PagedListResultsOfPersonSearchResultAevzrKY9」一類型的數據。反序列化器不知道映射到該名稱的任何類型。考慮更改DataContractResolver上的ResolveName方法的實現,以返回名稱爲'PagedListResultsOfPersonSearchResultAevzrKY9'和名稱空間'http://schemas.datacontract.org/2004/07/Contoso.Services.Contract.Infrastructure'的非空值。

我也遇到過字符串MZHTWXIT

我的哈克解決方法是先檢查類型是否已註冊,如果不是,再次檢查沒有最後八個字符。這看起來很不可靠,我想要一個更加簡單的方法來處理這個奇怪的附件。

實際問題:這是什麼字符串附加到typeName,我怎麼能阻止它被追加(或以其他方式處理)?


爲DataContractResolver全部源代碼如下:

public sealed class KnownTypesDataContractResolver : DataContractResolver 
{ 
    private readonly Dictionary<string, Type> _knownTypes; 

    public KnownTypesDataContractResolver(IEnumerable<Type> types) 
    { 
     _knownTypes = (
      from type in types.Distinct() 
      group type by type.FullName into g 
      select g.First()) 
      .ToDictionary(GetName); 
    } 

    public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, 
     DataContractResolver knownTypeResolver) 
    { 
     // I have no idea why this string gets appended to PagedListResult generic typename but removing it seems to work... 
     var genericTypeName = typeName.Contains("MZHTWXIT"); 
     var knownTypeName = genericTypeName ? typeName.Substring(0, typeName.IndexOf("MZHTWXIT")) : typeName; 

     Type type; 

     if (_knownTypes.TryGetValue(knownTypeName, out type)) 
      return type; 

     if (knownTypeName.StartsWith("ArrayOf")) 
     { 
      if (_knownTypes.TryGetValue("ListOf" + knownTypeName.Substring(7), out type)) 
       return type; 
     } 

     var withoutFinalEightChars = typeName.Substring(0, typeName.Length - 8); 
     if (_knownTypes.TryGetValue(withoutFinalEightChars, out type)) 
      return type; 

     return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null); 
    } 

    [DebuggerStepThrough] 
    public override bool TryResolveType(Type type, Type declaredType, DataContractResolver knownTypeResolver, 
     out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace) 
    { 
     if (!knownTypeResolver.TryResolveType(type, declaredType, null, out typeName, out typeNamespace)) 
     { 
      typeName = new XmlDictionaryString(XmlDictionary.Empty, type.Name, 0); 
      typeNamespace = new XmlDictionaryString(XmlDictionary.Empty, type.Namespace, 0); 
     } 

     return true; 
    } 

    private static string GetName(Type type) 
    { 
     return type.IsArray 
      ? "ArrayOf" + GetName(type.GetElementType()) 
      : type.IsGenericType ? GetGenericName(type) : type.Name; 
    } 

    private static string GetGenericName(Type type) 
    { 
     var typeDef = type.GetGenericTypeDefinition(); 
     var name = typeDef.Name.Substring(0, typeDef.Name.IndexOf('`')); 
     return name + "Of" + string.Join(string.Empty, type.GetGenericArguments().Select(GetName)); 
    } 
} 
+1

你檢查了以下內容:http://stackoverflow.com/questions/4616185,這也談到通用'PagedList'其中確切的類型名稱以一個看似隨機的後綴結尾? – Tamas

+0

@ Tamas-SonarSourceTeam - 很好找!我會檢查出來,謝謝 – AlexFoxGill

+1

另一個是http://stackoverflow.com/questions/172265 –

回答

1

正如How can I control the name of generic WCF return types?提到你可以使用使用Name財產這樣的DataContract屬性定義返回類型名稱:

[DataContract(Name = "ResponseOf{0}")] 
public class Response<T> 
+0

這個問題是它迫使你裝飾簡單的類與WCF具體屬性。我們怎樣才能實現這個沒有屬性? – Steven

+0

一種選擇是使用包含所有通用響應類型的共享庫(由客戶端和服務器使用)。在服務對話框中使用此庫。在這種情況下,服務器和客戶端的名稱應該相同。 –