programming oriented net c# .net reflection proxy aop

c# - oriented - net core aop



Cómo hacer un proxy dinámico simple en C# (7)

Quiero construir un objeto proxy dinámico para agregar cierta funcionalidad a un objeto.

básicamente quiero recibir un objeto, envolverlo con un objeto que se ve idéntico al original que obtuve e interceptar todas las llamadas.

class Wrapper : DynamicProxy// dynamic proxy is not a reall class, but i guess something like this exists... { public static T Wrap(T obj) { return (T) new Wrapper(obj); } public override object InterceptCall(MethodInfo info, object[] args) { // do stuff } }

Solo para aclarar, quiero hacer algo similar a la fábrica de canales de WCF ...

Estoy agregando un bounty, porque necesito una buena forma de usar proxy para las clases (no interfaces) y para manejar métodos no virtuales (como si heredara y añadiera un methond bajo la palabra clave "new"). Estoy seguro de que todo esto es muy posible ya que .Net lo hace.




Debería haber escrito esto antes, pero no importa.

Mi problema tenía un "problema" especial que necesitaba para poder usar clases proxy y no interfaces.

Hay dos soluciones para esto:

  1. Real Proxy y amigos, básicamente significa usar .Net Remoting. Requiere uno para heredar de ContextBoundObject.

  2. Creando un proxy usando System.Reflection.Emit como hecho antes de la spring también puedes mirar el código de su ProxyFactoryObject . Aquí hay another tres articles sobre el subject .

Por cierto, el segundo enfoque tiene una limitación considerable, no se pueden usar métodos no virtuales.


Echa un vistazo a PostSharp . No sé de una manera de hacer lo que quieres en vanilla .Net, pero PostSharp ofrece cosas como "OnMethodBoundaryAspect" que se puede utilizar para reemplazar o ajustar el código dentro del método.

Lo he usado para hacer cosas como registro, validación de parámetros, manejo de excepciones, etc.

Hay una edición comunitaria gratuita, que debería funcionar para usted. Lo necesitará instalado en su máquina de desarrollo, así como en cualquier servidor de compilación que utilice.


Otra opción es ContextBoundObject .

Hubo un artículo sobre CodeProject hace unos 8-9 años usando este enfoque para rastrear llamadas a métodos.


Para agregar cualquier funcionalidad antes y después de cada función en una clase, el proxy real es un buen enfoque.

Entonces ahora en T puede haber cualquier TestClass. Crear instancia como esta para TestClass-

var _instance = (object) DynamicProxy (TestClass) .GetTransparentProxy ();

El código para Dynamic Proxy-

class DynamicProxy<T> : RealProxy { readonly T decorated; public DynamicProxy(T decorated) : base(typeof(T)) { this.decorated = decorated; } public override IMessage Invoke(IMessage msg) { var methodCall = msg as IMethodCallMessage; var methodInfo = methodCall.MethodBase as MethodInfo; string fullMethodName = $"{methodInfo.DeclaringType.Name}.{methodCall.MethodName}"; try { var result = methodInfo.Invoke(decorated, methodCall.InArgs); return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall); } catch (Exception e) { return new ReturnMessage(e, methodCall); } finally { } } }


Puede hacer esto con una combinación de DynamicObject e ImpromptuInterface pero tendrá que tener una interfaz que implemente las funciones y propiedades que desea DynamicObject como proxy.

public interface IDoStuff { void Foo(); } public class Wrapper<T> : DynamicObject { private readonly T _wrappedObject; public static T1 Wrap<T1>(T obj) where T1 : class { if (!typeof(T1).IsInterface) throw new ArgumentException("T1 must be an Interface"); return new Wrapper<T>(obj).ActLike<T1>(); } //you can make the contructor private so you are forced to use the Wrap method. private Wrapper(T obj) { _wrappedObject = obj; } public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result) { try { //do stuff here //call _wrappedObject object result = _wrappedObject.GetType().GetMethod(binder.Name).Invoke(_wrappedObject, args); return true; } catch { result = null; return false; } } }

Por supuesto, podrías elegir perder el tipo de seguridad e ir con un objeto dinámico como yo mostré y luego soltar el lanzamiento de pato.

Hice una versión extensible transparente de este objeto proxy, y lo abrí here .