library ioc example description container c# .net ioc-container maintainability

c# - example - Código de crucero. IoC al rescate



autofac ioc container (4)

En question sobre la utilidad de IoC Container, el remitente ganador mencionó que con un contenedor IoC puede tomar esto:

public class UglyCustomer : INotifyPropertyChanged { private string _firstName; public string FirstName { get { return _firstName; } set { string oldValue = _firstName; _firstName = value; if(oldValue != value) OnPropertyChanged("FirstName"); } } private string _lastName; public string LastName { get { return _lastName; } set { string oldValue = value; _lastName = value; if(oldValue != value) OnPropertyChanged("LastName"); } } }

a esto:

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper());

Preguntas:

  • ¿Qué contenedor mágico IoC proporciona esta bondad?
  • ¿Un ejemplo implementando esto?
  • ¿Alguna desventaja?
  • En un proyecto con dependencias complejas, ¿estaré llorando cuando intente aplicar el enlace de datos a estos objetos?

Nunca lo he usado, pero supuestamente puedes crear algo como esto usando PostSharp .


Para hacer esto de manera genérica (es decir, una sola pieza de código que implementa INotifyPropertyChanged para cualquier clase) use un proxy. Hay muchas implementaciones para hacer esto con Castle.DynamicProxy o LinFu o Unity . Estas bibliotecas proxy tienen un buen soporte en los contenedores IoC, por ejemplo, DynamicProxy tiene una buena integración con Castle Windsor y la intercepción Unity (o como se llame) tiene una buena integración con el contenedor Unity.


Para que funcione su segundo fragmento de código, NotifyPropertyChangedWrapper tendría que usar la reflexión (o dynamic ) para generar una clase que proporcione una interfaz compatible con el Customer e implemente la notificación automática de propiedad. No debería haber problemas de enlace de datos, pero habría una pequeña sobrecarga.

Una implementación simplificada que utiliza un objeto dinámico podría tener este aspecto:

public class NotifyPropertyChangedWrapper<T> : DynamicObject, INotifyPropertyChanged { private T _obj; public NotifyPropertyChangedWrapper(T obj) { _obj = obj; } public override bool TryGetMember( GetMemberBinder binder, out object result) { result = typeof(T).GetProperty(binder.Name).GetValue(_obj); return true; } // If you try to set a value of a property that is // not defined in the class, this method is called. public override bool TrySetMember( SetMemberBinder binder, object value) { typeof(T).GetProperty(binder.Name).SetValue(_obj, value); OnPropertyChanged(binder.Name); return true; } // Implement OnPropertyChanged... }

Obviamente, cualquier código que consuma uno de estos objetos perdería cualquier tipo de seguridad estática. La otra opción es generar una clase implementando la misma interfaz que la clase envuelta. Hay muchos ejemplos para esto en la web. El principal requisito es que su Customer debería ser una interface o necesitaría que todas sus propiedades sean virtuales.


Si está buscando una solución específica para la generación automática de objetos enlazables, debería consultar PropertyChanged.Fody (anteriormente NotifyPropertyWeaver). Esto vuelve a escribir las clases que implementan INotifyPropertyChanged para incluir el código de notificación. Hay un ejemplo en la página github.

En mi opinión, esto es mejor que utilizar la solución de contenedor propuesta de IOC. Sin embargo, es una biblioteca específica para el enlace INotifyPropertyChanged, por lo que no es aplicable como una solución general, como se discutió en su pregunta vinculada.