2011-05-02 22 views
7

Silverlight'ta seri hale getirmeye çalışırken bir istisna alıyorum. Test2 başarısız olur, Test2 başarılı olur. Ayrıca hem Basit hem de Tam olarak TypeNameAssemblyFormat denedim, ancak aynı sonuçları alın. Test2 montajı çözebilir, neden Json.NET olamaz?Json.NET Silverlight'ta TypeNameHandling.Objects ile nasıl deserialize olabilirim?

Güncelleme: Deserialize denemek istediğim türden bahsetmeyi unuttum, deserializasyonun oluştuğu silverlight derlemesinden farklı bir montajda tanımlanır.

Her iki test de non-silverlight .NET uygulamasında çalışır.

Tipenleri olan bir json dizgisini nasıl deserialize edebilirim?

private void Test1() 
{ 
    JsonSerializerSettings settings = new JsonSerializerSettings(); 
    settings.TypeNameHandling = TypeNameHandling.Objects; 
    string json1 = "{\"$type\":\"AmberGIS.NetworkTrace.DTO.NTPoint, NetworkTrace.DTO.Assembly\",\"X\":0.0,\"Y\":0.0,\"SpatialReference\":null}"; 
    try 
    { 
     var n1 = JsonConvert.DeserializeObject<NTPoint>(json1, settings); 
     //Error resolving type specified in JSON 'AmberGIS.NetworkTrace.DTO.NTPoint, NetworkTrace.DTO.Assembly'. 
     //Could not load file or assembly 'NetworkTrace.DTO.Assembly, Culture=neutral, PublicKeyToken=null' or one of its dependencies. 
     //The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest. 
     //(Exception from HRESULT: 0x80131053) 
    } 
    catch (Exception ex) 
    { 
     while (ex != null) 
     { 
      Debug.WriteLine(ex.Message); 
      ex = ex.InnerException; 
     } 
    } 
} 

Bu Test2 başarılı:

private void Test2() 
{ 
    var pnt1 = new AmberGIS.NetworkTrace.DTO.NTPoint(); 
    Debug.WriteLine(pnt1.GetType().AssemblyQualifiedName); 
    // "AmberGIS.NetworkTrace.DTO.NTPoint, NetworkTrace.DTO.Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" 

    string fullName = "AmberGIS.NetworkTrace.DTO.NTPoint, NetworkTrace.DTO.Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"; 
    var t = Type.GetType(fullName); 
    var pnt2 = Activator.CreateInstance(t) as NTPoint; 

} 
+0

kullanarak: montaj bilgisi bütün (iç içe) nesneler üzerinde yineleme ve ekleyerek JSON değiştirmek böylece olacak cevapsız listede görünmüyor mu? – keyr

+0

@keyr, ancak daha az hacky çözümü için umuyordum. –

cevap

6

deneyin ekleyerek ayarlarını JsonConvert.DeserializeObject<T>(json, Settings), nerede Ayarlar geçerli:

sorun şu ki:

new JsonSerializerSettings 
       { 
        TypeNameHandling = TypeNameHandling.Objects, 
        TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full 
       } 
+0

Teşekkürler! Hayatımı çok basitleştirdin. –

+2

Bunu denedim ve işe yaramadı. Hala System.IO.FileLoadException özel durumunu alıyorum: Dosya veya derleme yüklenemedi ... veya bağımlılıklarından biri. İstenen derleme sürümü, uygulama etki alanında önceden bağlı olan veya bildirimde belirtilmiş olanla çakışır ... Sorunun, sürüm de dahil olmak üzere tüm derleme bilgileri dahil edilmediyse, çalışmadığını görüyorum. Bunun nedeni, OP'nin özellikle TypeNameAssemblyFormat = FormatterAssemblyStyle.Full dosyasının çalışmadığı için neden kabul edildiğini de karıştırdı. –

+0

Aman Tanrım. Çok teşekkür ederim! İlk bölüm vardı, ancak TypeNameAssemblyFormat hakkında bilmiyordum. –

2

Ben Json.NET 4.0r2 için kaynak indirerek ve aşağıda gösterildiği gibi, DefaultSerializationBinder.cs için kesmek 2 kod satırını ekleyerek sorunumu çözdü. Bu muhtemelen güçlü adlandırılmış montajlar için çalışmayacak. Silverlight yüklü derlemeler için appdomain'i taramak için bir yöntemden yoksundur, bkz. here.

#if !SILVERLIGHT && !PocketPC 
     // look, I don't like using obsolete methods as much as you do but this is the only way 
     // Assembly.Load won't check the GAC for a partial name 
#pragma warning disable 618,612 
     assembly = Assembly.LoadWithPartialName(assemblyName); 
#pragma warning restore 618,612 
#else 
      // **next 2 lines are my hack** ... 
      string fullName = String.Format("{0}, {1}, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",typeName,assemblyName); 
      return Type.GetType(fullName); 

     assembly = Assembly.Load(assemblyName); 
#endif 
1

Ben Json.NET değiştirerek gerektirmediğini burada çözüm ilanıyla satır Silverlight için yeterli değil:

string json1 = "{\"$type\":\"AmberGIS.NetworkTrace.DTO.NTPoint, NetworkTrace.DTO.Assembly\" ... }"; 

Bu ihtiyacı:

string json1 = "{\"$type\":\"AmberGIS.NetworkTrace.DTO.NTPoint, NetworkTrace.DTO.Assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null \", ...}"; 

Yani JSON (bir sunucudan geliyordu ve Json.NET tarafından oluşturulan değildi çünkü benim durumumda JSON değiştirilemedi) de dahil olmak üzere tarzım elle etmektir

string json = <some json you want fixed> 
Type type = <the target type you want> 
JObject jsonObject = JObject.parse (json); 
jsonObject["$type"] = type.FullName + ", " + type.Assembly.FullName; 
json = jsonObject.ToString(Formatting.None, null); 

Sonra her zamanki gibi serisini Neden cevap olarak çözüm ekleyin ve kabul etmiyoruz

JsonSerializerSettings settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; 
var n1 = JsonConvert.DeserializeObject<NTPoint>(json, settings); 
+0

Bu çözüm benim için çalıştı, yine de, seriyi kaldırma işleminden önce jsonu el ile kullanmayı beceremedim.Başka bir yaklaşımın, aynı isimle ortak bir model montajına sahip olması ve bir gümüş yapıya/versiyonuna sahip olabileceğini düşünüyorum. – santos

İlgili konular