2016-08-08 65 views
2

Ich habe eine JSON-Zeichenfolge z.JSON.NET Deserialize-Schnittstelle zum Attributnamen

{ 
    "first_name": "Paul" 
    "company": { 
    "company_name": "Microsoft" 
    } 
} 

und meine Klasse ist in der folgenden Struktur

[DataContract] 
class User { 
    [DataMember(Name = "first_name")] 
    public string FirstName { get; set; } 

    [DataMember(Name = "company")] 
    public ICompany Company { get; set; } 
} 

interface ICompany { 
    string CompanyName { get; set; } 
} 

[DataContract] 
class Company : ICompany { 
    [DataMember(Name = "company_name")] 
    public string CompanyName { get; set; } 
} 

ich ein benutzerdefiniertes Auto-Resolver verwenden, die nur eine Implementierung einer Schnittstelle Autofac findet (von json.net Webseite gezogen)

public class AutofacContractResolver : DefaultContractResolver 
    { 
     private readonly IContainer _container; 

     public AutofacContractResolver(IContainer container) 
     { 
      _container = container; 
     } 

     protected override JsonObjectContract CreateObjectContract(Type objectType) 
     { 
      JsonObjectContract contract = base.CreateObjectContract(objectType); 

      // use Autofac to create types that have been registered with it 
      if (_container.IsRegistered(objectType)) 
      { 
       contract.DefaultCreator =() => _container.Resolve(objectType); 
      } 

      return contract; 
     } 
    } 

Ich deserialize dann die JSON-Zeichenfolge mit

User user = JsonConvert.DeserializeObject<User>(json, new JsonSerializerSettings 
       { 
        ContractResolver = _resolver, 

       }); 

Wenn ich jetzt den JSerialisiere, wird der Vorname in die FirstName-Eigenschaft serialisiert, aber der Firmenname nicht, es gibt nur null zurück. Wenn ich den TraceWriter benutze, gibt es an, dass er kein Mitglied namens company_name auf der ICompany-Schnittstelle finden kann (was offensichtlich nicht für die Objektklasse Company möglich ist).

Warum verwendet JSON.NET den DataMember-Namen nicht von der Objekt deserialisieren gegen? Da es über das Compnany-Objekt aus dem benutzerdefinierten Resolver weiß, erstellt es dieses Objekt aber nur ohne Werte innerhalb.

Wie bekomme ich es, die Implementierung der Schnittstelle und nicht die Schnittstelle selbst zu verwenden?

FYI, das ist nicht das ganze Objekt und ich kann nicht nur meine Eigenschaft in eine Klasse statt einer Schnittstelle ändern. Dies ist nur ein abgespecktes Beispiel dafür, was mit allen Schnittstellenobjekten geschieht.

Antwort

2

Ich hatte gerade das gleiche Problem und auf der Suche nach einer Antwort habe ich Ihre alte Frage hier gefunden. Eigentlich hat mich die Art und Weise, wie du sie gefragt hast, auf den richtigen Weg gebracht und ich habe das Problem gelöst. Folgendes funktioniert für mich:

Ich benutze kein Autofac, also ist das Pseudocode. Aber es sollte genug sein, um es zu verstehen:

public class AutofacContractResolver : DefaultContractResolver 
{ 
    private readonly IContainer _container; 

    public AutofacContractResolver(IContainer container) 
    { 
     _container = container; 
    } 

    protected override JsonObjectContract CreateObjectContract(Type objectType) 
    { 
     JsonObjectContract contract; 

     // use Autofac to create types that have been registered with it 
     if (_container.IsRegistered(objectType)) 
     { 
      //get the class that is mapped to the interface from autofac 
      Type mappedType = _container.GetMappedTypeForRegisteredType(objectType); 

      //so for example when objectType now contains 'ICompany' 
      //then mappedType now should contain 'Company' 

      //now use the mappedType to create the contract 
      contract = base.CreateObjectContract(mappedType); 

      //but still use the objectType for resolving 
      contract.DefaultCreator =() => _container.Resolve(objectType); 
     } 
     else 
      contract = base.CreateObjectContract(objectType); 

     return contract; 
    } 
} 

Der Vertrag erstellt werden soll, die konkrete Umsetzung verwenden, die anstelle der Schnittstelle in den Abhängigkeits Containern registriert ist. Das Auflösen des Typs aus dem Container für den DefaultCreator sollte natürlich weiterhin die Schnittstelle verwenden.