2016-08-08 5 views
2

예 : JSON 문자열이 있습니다. JSON.NET 속성 이름에 대한 인터페이스 비 직렬화

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

내 클래스 (json.net 웹 사이트에서 가져온)

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

난 그냥 autofac를 사용하여 인터페이스의 구현을 발견 사용자 정의 자동 해결 프로그램을 사용하여 다음과 같은 구조에

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

그때

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

       }); 
를 사용하여 JSON 문자열을 역 직렬화

이제 json을 deserialize 할 때 first_name은 FirstName 속성으로 serialize되지만 company_name은 serialize되지 않고 null 만 반환합니다. TraceWriter를 사용하면 ICompany 인터페이스에서 company_name이라는 멤버를 찾을 수 없다는 것을 알 수 있습니다 (회사 개체 클래스에서 설정할 수는 없습니다).

왜 JSON.NET은 반대로 역 직렬화 할 회사 개체? 그것은 사용자 정의 리졸버로부터의 Compmany 객체에 대해 알고 있고 그 객체를 생성하지만 내부에는 값이 없습니다.

인터페이스 자체가 아닌 인터페이스 구현을 사용하려면 어떻게해야합니까?

참고로, 이것은 전체 개체가 아니며 클래스 대신 내 속성을 인터페이스로 변경할 수 없습니다. 이것은 모든 인터페이스 객체에 어떤 일이 일어나고 있는지에 대한 단순한 예입니다.

답변

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의 컨테이너에서 형식을 확인하는 작업은 여전히 ​​인터페이스를 사용해야합니다.