¿Cuál es el camino más corto para implementar un proxy o clase decoradora en c #?
-
21-08-2019 - |
Pregunta
Cuando usted tiene un coche de la clase que implementa IVehicle y desea envolverlo en un decorador que reenvía todas las llamadas al coche y los cuenta, ¿cómo hacerlo?
En Rubí tan sólo pudiera construir un decorador sin ningún tipo de métodos y utilizar method_missing para desviar todas las llamadas al objeto coche.
En Java podría construir un objeto proxy que se ejecuta todo el código a través de un método y lo envía después.
¿Hay alguna cosa similar que pueda hacer en C #?
Actualización:
basado en las answeres y lo que he leído sobre System.Reflection.Emit debería ser posible escribir un método similar a este:
Type proxyBuilder(Type someType, delagate functionToBeApplied, Object forward)
donde tipo implementa todo el interfaz de sometype, ejecuta functionToBeApplied y luego reenvía la llamada al método de oponerse al regresar su retorno.
¿Hay alguna lib que hace precisamente eso, o tendría que escribir mi propia?
Solución
Para hacer proxy que podría mirar en "RealProxy" si desea utilizar los tipos estándar, que es un poco de una molestia de usar, aunque (y requiere sus clases heredan de MarshalByRefObject).
public class TestProxy<T> : RealProxy where T : class
{
public T Instance { get { return (T)GetTransparentProxy(); } }
private readonly MarshalByRefObject refObject;
private readonly string uri;
public TestProxy() : base(typeof(T))
{
refObject = (MarshalByRefObject)Activator.CreateInstance(typeof(T));
var objRef = RemotingServices.Marshal(refObject);
uri = objRef.URI;
}
// You can find more info on what can be done in here off MSDN.
public override IMessage Invoke(IMessage message)
{
Console.WriteLine("Invoke!");
message.Properties["__Uri"] = uri;
return ChannelServices.SyncDispatchMessage(message);
}
}
Como alternativa se puede conseguir "DynamicProxy" de Castillo .. Funciona un poco mejor en mi experiencia ..
Si se utiliza uno de los que no necesariamente siempre obtendrá un gran rendimiento sin embargo, los utilizo principalmente en las llamadas que probablemente será lento en el primer lugar .. Pero se puede probarlo si lo desea.
La solución de Marc tendrá un mejor rendimiento.
Otros consejos
Por desgracia, no hay apoyo mixin en C #. Así que había necesidad de poner en práctica todos los métodos, o utilizar algún Reflection.Emit de alta resistencia para hacerlo. La otra alternativa es una (opcional) clase de proxy / base decorador ...
abstract class FooBase : IFoo {
protected FooBase(IFoo next) {this.next = next;}
private readonly IFoo next;
public virtual void Bar() { // one of the interface methods
next.Bar();
}
public virtual int Blop() { // one of the interface methods
return next.Blop();
}
// etc
}
entonces
class SomeFoo : FooBase {
public SomeFoo(IFoo next) : base(next) {}
public override void Bar() {...}
}
Tras señalar que el uso de la FooBase
es estrictamente opcional; Se permite cualquier IFoo.