visual valores valor tipos tener studio que programas objeto numeros declarar debe datos comparar acepta c# json.net

c# - tipos - Interceptar población de lista para asignar valores en deserialización



programas en c# (1)

Su problema es que está intentando subclasificar la List<T> para mantener las relaciones padre / hijo a medida que los elementos se agregan y eliminan de la lista, sin embargo, List<T> no está diseñado para ser subclasificado de esta manera ya que ninguno de los métodos relevantes son virtual. En su lugar, está ocultando el método Add() través de public new CartItem Add(CartItem item) , sin embargo, resulta que Json.NET no llama a este método de reemplazo (y no hay ninguna razón para suponer que lo haría).

En su lugar, debe usar Collection<T> que está expresamente diseñado para este propósito. De los documentos :

La clase Collection<T> proporciona métodos protegidos que se pueden usar para personalizar su comportamiento al agregar y eliminar elementos, borrar la colección o establecer el valor de un elemento existente.

Por lo tanto, su modelo de objetos debería ser similar a lo siguiente:

public class CartItems : Collection<CartItem> { public CartItems() : base() { } public CartItems(CartItem parent) : this() { this.Parent = parent; } public CartItem Parent { get; private set; } protected override void RemoveItem(int index) { CartItem oldItem = null; if (index >= 0 && index < Count) { oldItem = this[index]; } base.RemoveItem(index); } protected override void InsertItem(int index, CartItem item) { base.InsertItem(index, item); if (item != null) item.Parent = this; } protected override void SetItem(int index, CartItem item) { CartItem oldItem = null; if (index >= 0 && index < Count) { oldItem = this[index]; } base.SetItem(index, item); if (oldItem != null) oldItem.Parent = null; if (item != null) item.Parent = this; } protected override void ClearItems() { foreach (var item in this) if (item != null) item.Parent = null; base.ClearItems(); } } public class CartItem { public CartItem() { this.Children = new CartItems(this); } public int t { get; set; } public int i { get; set; } public int n { get; set; } public bool r { get; set; } [JsonProperty("c")] public CartItems Children { get; private set; } [JsonIgnore] public CartItems Parent { get; set; } }

Observe que tanto CartItem como CartItems tienen una propiedad Parent . CartItems.Parent se asigna en su constructor. CartItem.Parent se asigna mediante los InsertItem reemplazados InsertItem , SetItem y RemoveItem .

Muestra de violín .

Consulte también Collection<T> versus List<T> ¿qué debería usar en sus interfaces? .

Tengo una clase recursiva (jerarquía de árbol), que se deriva de una lista, que tiene los hijos y, a su vez, poblada de la deserialización en JSON.NET.

La versión de TLDR es que deseo llenar una variable en los elementos secundarios, desde el elemento primario, en cada nivel de esta clase donde exista, sin utilizar las variables $ ref de JSON.NET (ahorra espacio cuando se almacena en una cookie).

Para aquellos que siguieron mi pregunta de ayer, esto puede parecer un duplicado, pero no lo es. Es el mismo código, pero la vieja pregunta giraba en torno a setters en JSON que no se activaban (resueltos), y la respuesta generaba esta pregunta (más acertadamente redactada).

La llamada inicial sería:

_Items = Cookies.Instance.GetJObject<CartItems>(COOKIE, jsonSetting);

Que llama:

public T GetJObject<T>(string cookieName, JsonSerializerSettings jset = null) { string cookieContent = Get(cookieName); return JsonConvert.DeserializeObject<T>(cookieContent, jset); }

La clase de convertidor personalizado es la siguiente:

public class JsonCartConverter : JsonConverter { public override bool CanConvert(Type objectType) { return typeof(CartItem).IsAssignableFrom(objectType); } public override bool CanWrite { get { return false; } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject obj = JObject.Load(reader); var type = obj["t"] != null ? (CARTITEMTYPE)obj["t"].Value<int>() : CARTITEMTYPE.GENERIC; var item = CartItems.NewByType(type); serializer.Populate(obj.CreateReader(), item); return item; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { } }

El JSON resultante es el siguiente:

[{"t":1,"i":1,"n":4,"r":false,"c":[{"t":5,"i":2,"n":4,"r":false,"c":[]}]},{"t":1,"i":3,"n":4,"r":false,"c":[{"t":5,"i":4,"n":4,"r":false,"c":[{"t":4,"i":6,"n":14,"r":false,"c":[]}]},{"t":1,"i":5,"n":15,"r":false,"c":[]}]}]

Y lo que estoy tratando de hacer, sería similar a esto:

public class CartItems : List<CartItem>{ public new CartItem Add(CartItem item) { item.Parent = this; base.Add(item); return item; }

Entonces, el problema es que hemos establecido que la deserialización no llama a los métodos estándar Agregar / Insertar de una Lista para llenar una lista. Sabemos que está creando la lista a través de la reflexión, pero ¿cómo? ¿Puedo interceptar la asignación de la clase hija a la clase padre, luego de la inserción, para asignarle una variable en la clase hija de la clase principal (es decir, child.Parent = this)?

Intenté hurgar en JSON.NET source para encontrar el método en una colección que está utilizando para rellenar (porque incluso con la reflexión, tiene que agregarlos invocando una llamada al método, ¿no?). A menos que ... esté haciendo algo como esto:

CartItems items = new CartItems() { new GenericItem() { }, new GenericItem() { } };

Editar: CartItems es la clase derivada de la lista. Se rellena con varias instancias de CartItem.