2016-08-08 6 views
2

JSON文字列があります。JSON.NET属性名へのインタフェースの逆シリアル化

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

と私のクラス私はちょうど(json.netウェブサイトから引き出さ)autofacを使用して、インタフェースの実装を見つけたカスタム自動リゾルバを使用して、以下の構造

[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; } 
} 

である

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; 
     } 
    } 

これを使ってjson文字列を逆シリアル化します。

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

       }); 

jsonを非直列化すると、first_nameプロパティがFirstNameプロパティにシリアル化されますが、company_nameはシリアル化されず、nullが返されます。 TraceWriterを使用すると、ICompanyインターフェイス上でCompany_nameというメンバーを見つけることができないことがわかります(Companyオブジェクトクラスで設定されているとおりにはできません)。

JSON.NETは、デシリアライズする企業オブジェクトカスタムリゾルバからのCompmanyオブジェクトについて知っているので、そのオブジェクトを作成しますが、その内部には値はありません。

インターフェイス自体ではなくインターフェイスの実装を使用するにはどうすればよいですか?

FYI、これはオブジェクト全体ではなく、インターフェイスではなくクラスにプロパティを変更するだけではありません。これは、すべてのインタフェースオブジェクトに何が起こっているのかを少しスリムにした例です。

答えて

2

私はちょうど同じ問題を抱えていました。答えを探しているうちに私はあなたの古い質問を見つけました。実際にあなたが尋ねたやり方は、正しい軌道に乗ってくれました。問題を解決しました。以下は私のために働く:

私はAutofacを使用しないので、これは擬似コードです。しかし、それを理解するのに十分でなければならない:

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; 
    } 
} 

契約ではなく、インターフェースの依存コンテナに登録されている具体的な実装を使用して作成する必要があります。 DefaultCreatorのコンテナから型を解決するには、明らかにこのインターフェイスを使用する必要があります。

関連する問題