직렬화에 생성자 호출을 피할 수있는 최선의 선택은 JsonConstructor 속성으로 표시 생성자없이 모든 클래스에 대한 생성자 함수를 오버라이드 (override) 특별 계약 리졸버를 만드는 것입니다. 이 방법으로 JSON.NET이 정말로 필요한 경우 생성자를 호출하도록 강요 할 수 있지만 다른 모든 클래스는 .NET의 표준 DataContract serializer와 매우 비슷하게 생성됩니다. 코드는 다음과 같습니다.
/// <summary>
/// Special contract resolver to create objects bypassing constructor call.
/// </summary>
public class NoConstructorCreationContractResolver : DefaultContractResolver
{
/// <summary>
/// Creates a <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/> for the given type.
/// </summary>
/// <param name="objectType">Type of the object.</param>
/// <returns>
/// A <see cref="T:Newtonsoft.Json.Serialization.JsonObjectContract"/> for the given type.
/// </returns>
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
// prepare contract using default resolver
var objectContract = base.CreateObjectContract(objectType);
// if type has constructor marked with JsonConstructor attribute or can't be instantiated, return default contract
if (objectContract.OverrideConstructor != null || objectContract.CreatedType.IsInterface || objectContract.CreatedType.IsAbstract)
return objectContract;
// prepare function to check that specified constructor parameter corresponds to non writable property on a type
Func<JsonProperty, bool> isParameterForNonWritableProperty =
parameter =>
{
var propertyForParameter = objectContract.Properties.FirstOrDefault(property => property.PropertyName == parameter.PropertyName);
if (propertyForParameter == null)
return false;
return !propertyForParameter.Writable;
};
// if type has parameterized constructor and any of constructor parameters corresponds to non writable property, return default contract
// this is needed to handle special cases for types that can be initialized only via constructor, i.e. Tuple<>
if (objectContract.ParametrizedConstructor != null
&& objectContract.ConstructorParameters.Any(parameter => isParameterForNonWritableProperty(parameter)))
return objectContract;
// override default creation method to create object without constructor call
objectContract.DefaultCreatorNonPublic = false;
objectContract.DefaultCreator =() => FormatterServices.GetSafeUninitializedObject(objectContract.CreatedType);
return objectContract;
}
}
직렬화 설정 전에 직렬화 설정에서 필요한 모든 것이 간단합니다.
AFAIK. 생성자는 인스턴스를 만들 때 항상 실행됩니다. – Maarten
@Maarten http://msdn.microsoft.com/en-us/library/system.runtime.serialization.formatterservices.getsafeuninitializedobject.aspx –
고맙습니다. 오늘 뭔가를 배웠습니다 :-) – Maarten