Я хочу сериализовать определенные приватные поля, принадлежащие классу неизменяемой библиотеки, как я могу это сделать?
Для сериализации приватных полей я знаю, что могу изменить настройки для сериализации всех приватных полей, но я делаюне хочу сериализовать все поля. Только конкретные поля.
Также для сериализации приватных полей я знаю, что атрибуты JsonProperty или DataMember могут быть записаны в приватных полях. Но я не могу этого сделать, потому что я не могу изменять библиотечные классы. Даже если я могу изменить ее, библиотека зависит от внешней библиотеки после изменения класса библиотеки (например, это зависит от Newtonsoft.Json.dll, если используется атрибут JsonProperty).
Поэтому я попытался создать пользовательскийатрибут, чтобы решить это.
// The class to serialize
public class FeatureRepository
{
// Serialize all private properties that belongs to this object.
public IDGenerator FeatureIDs;
// Do not serialize any private property that belongs to this object!
public IDGenerator oldFeatureIDs;
}
// Unmodifiable library class. Also it must be independent from any external libraries.
// There are some private fields but they do not seem.
public class IDGenerator
{
public IDGenerator();
public uint GenerateID();
public bool IsIDUsed(uint id);
public void ReleaseID(uint id);
public void UseID(uint id);
}
// Custom contract resolver
public class MyContractResolver : DefaultContractResolver
{
// Target properties
private List<SerializableJson> serializableJsons = new List<SerializableJson>();
protected override JsonObjectContract CreateObjectContract(Type objectType)
{
JsonObjectContract contract = base.CreateObjectContract(objectType);
// Detect SerializableJsonAttribute and store the property info
foreach (JsonProperty property in contract.Properties)
{
IList<Attribute> attributes = property.AttributeProvider.GetAttributes(typeof(SerializableJsonAttribute), false);
foreach (SerializableJsonAttribute temp in attributes)
{
if (temp != null)
{
SerializableJson serializableJson = new SerializableJson()
{
PropertyType = property.PropertyType,
PropertyName = property.PropertyName
};
serializableJsons.Add(serializableJson);
}
}
}
return contract;
}
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
List<MemberInfo> members = base.GetSerializableMembers(objectType);
// It can compare just the type, can not compare the property name here.
SerializableJson serializableJson = serializableJsons.Where(temp => temp.PropertyType == objectType).FirstOrDefault();
// If the type is target type, add also private fields.
if (serializableJson != null)
{
IEnumerable<MemberInfo> nonPublicMembers = GetFieldsAndProperties(objectType, BindingFlags.NonPublic)
.Where(m => m is PropertyInfo p ? !IsIndexedProperty(p) : true);
foreach (MemberInfo member in nonPublicMembers)
members.Add(member);
}
return members;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class, AllowMultiple = false)]
public class SerializableJsonAttribute : Attribute
{
}
public class SerializableJson
{
public Type PropertyType { get; set; }
public string PropertyName { get; set; }
}
// Finally use the custom attribute SerializableJson
// Both of them will serialized with theirs private fields.
public class FeatureRepository
{
[SerializableJson]
public IDGenerator FeatureIDs; // I want to serialize all private properties that belongs to this object.
public IDGenerator oldFeatureIDs; // I do not want to serialize any private property that belongs to this object!
}
Как я могу это решить? Или есть другой способ решить эту проблему, чем я пытался?
Цитата
Редактировать Позвольте мне объяснить проблему шаг за шагом: во-первых, FeatureRepository сериализуется, SerializableJsonAttribute ищется для всех свойств. Он находит атрибут в свойстве FeatureIDs, но oldFeatureIDs. Таким образом, он хранит тип свойства "IDGenerator" и имя свойства "FeatureIDs". Во-вторых, он начинает сериализовать IDGenerator. При сериализации IDGenerator вы не можете знать, что сериализация выполнена для свойства FeatureIDs или свойства oldFeatureIDs. Если вы знаете, вы можете добавить приватные поля для свойства FeatureID.