52 votes

Comment faire un simple proxy dynamique en C#

Je veux construire une dynamique de l'objet proxy pour ajouter certaines fonctionnalités à un objet.

fondamentalement, je veux recevoir un objet, l'envelopper avec un objet qui ressemble à l'identique à l'original que j'ai eu, et d'intercepter tous les appels.

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
    }

}

Juste pour clarifier, je veux faire quelque chose de similaire à la WCF canal de l'usine...


Je suis en ajoutant une prime, parce que j'ai besoin d'un bon moyen de classes proxy (pas d'interfaces) et à gérer non des méthodes virtuelles (comme si j'avais hérité et a ajouté une methond dans le cadre du "nouveau" mot clé). Je suis sûr que tout cela est très possible que l' .Net t-il.

41voto

albertjan Points 3679

Vous pouvez le faire avec une combinaison de DynamicObject et ImpromptuInterface mais vous devrez avoir une Interface qui implémente les fonctions et les propriétés que vous voulez 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;
        }
    }
}

Vous pourriez bien sûr choisir de perdre le type de sécurité et d'aller avec une DynamicObject comme je l'ai montré, puis déposez le canard-casting.

J'ai fait un transparant extensible version de cet objet proxy, et opensourced il ici.

16voto

Harry Steinhilber Points 2603

En plus du Château.DynamicProxy, il y a aussi LinFu.DynamicProxy sur Github.

15voto

AK_ Points 2169

Je l'aurais écrit plus tôt, mais jamais l'esprit.

Ma question avait un spécial "gotcha" j'avais besoin d'être en mesure de classes de proxy et de ne pas les interfaces.

Il y a deux solutions à cela:

  1. Proxy, et des amis, fondamentalement signifie que l'aide .Net Remoting. Il faut hériter de ContextBoundObject.

  2. La construction d'un proxy à l'aide du Système.De la réflexion.Émettent comme le fait le printemps , vous pouvez aussi regarder le code de leur ProxyFactoryObject. Voici un autre trois articals sur le sujet.

Par ailleurs, la deuxième approche a une limitation considérable, vous ne pouvez pas proxy non des méthodes virtuelles.

5voto

NeilD Points 974

Jetez un oeil à PostSharp. Je ne sais pas un moyen de faire ce que vous voulez dans la vanille .Net, mais PostSharp offre des choses comme "OnMethodBoundaryAspect" qui peut être utilisé pour remplacer ou placer le code dans la méthode.

Je l'ai utilisé pour faire des choses comme l'exploitation forestière, la validation des paramètres, gestion des exceptions, etc.

Il y a une Communauté libre Édition, qui devrait fonctionner pour vous. Vous aurez besoin de l'installer sur votre machine de développement, ainsi que toute accumulation de serveur que vous utilisez.

2voto

parapura rajkumar Points 16597

Ici est simple exemple de la Dynamique de la Création de Proxy à l'Aide de C# Emit

Vous pouvez également utiliser un AOP cadre comme PostSharp

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X