2009-02-03 10 views
7

Cuando tienes un coche de clase que implementa un vehículo y quieres envolverlo en un decorador que reenvía todas las llamadas al automóvil y las cuenta, ¿cómo lo harías?¿Cuál es la forma más corta de implementar una clase proxy o decorador en C#?

En Ruby podría simplemente construir un decorador sin ningún método y usar method_missing para reenviar todas las llamadas al objeto del automóvil.

En Java podría construir un objeto Proxy que ejecute todo el código a través de un método y lo reenvíe posteriormente.

¿Hay algo similar que pueda hacer en C#?


actualización:

basado en los 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 toda la interfaz de someType, ejecuta functionToBeApplied y luego reenvía la llamada de método al objeto mientras devuelve su devolución.

¿Existe alguna lib que haga exactamente eso o tendría que escribir la mía?

Respuesta

4

Para el proxying se puede mirar en "RealProxy" si se quieren usar tipos estándar, sin embargo es un poco complicado de usar (y requiere que sus clases hereden 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); 
    } 
} 

Alternativamente, usted podría conseguir "DynamicProxy" de Castillo .. Funciona un poco mejor en mi experiencia ..

Si utiliza uno de los que no se neccessarily obtener un gran rendimiento sin embargo, yo uso principalmente en llamadas que probablemente serán lentas en primer lugar ... Pero podrías intentarlo si quieres.

La solución de Marc tendrá un mejor rendimiento.

2

Desafortunadamente, no hay soporte de mixin en C#. Por lo tanto, necesitaría implementar todos los métodos, o usar algunos reflectores de alta resistencia. Deje de hacerlo. La otra alternativa es un (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() {...} 
} 

Tomando nota de que el uso del FooBase es estrictamente opcional; cualquier IFoo está permitido.

+0

por favor, explique en pocas palabras, ¿qué significa "uso de' FooBase' es estrictamente opcional "? ¿Es predicado que "cualquier' IFoo' está permitido "? el punto y coma me hace leer la (s) declaración (es) por separado y el argumento es autosuficiente para agregar la confusión. a pesar de cpt. Susurros obvios: "solo significa que 'FooBase' puede ser reemplazado por cualquier otro 'IFoo', implementando 'IFoo' de una manera 'lo hace FooBase'", me decepcionará si es así de simple. No estoy decepcionado con la respuesta que es buena, sino con mi paranoia. perdón por "verboseness" (ahora necesito encontrar modismo, correspondiendo este fenómeno) –

+1

Creo que es su respuesta decepcionante; el código solo debería depender de 'IFoo'; 'FooBase' es solo una conveniencia para el código que elige implementar' IFoo'. –

+0

gracias!si tiene tiempo, responda dos preguntas más: ** 1) ** este tema ya tiene 6 años, parece que nada ha cambiado desde entonces y las formas de resolver el problema siguen siendo las mismas. * (nunca pensé que echaría de menos C++, pero tiene '->' sobrecarga) * ** 2) ** me equivoco: ¿estás diciendo que es una mala práctica heredar de las clases abstractas? Yo mismo los considero interfaces con la implementación predeterminada y son bastante convenientes. y puede referirse a instancias 'SomeFoo' como' IFoo', aparentemente. * (mientras tanto, MS implementó el polimorfismo de los métodos de extensión ...) * –

Cuestiones relacionadas