web-dev-qa-db-fra.com

Implémentation dynamique d'une interface dans .NET 4.0 (C #)

Avec les nouvelles capacités dynamiques de .NET 4.0, il semble qu'il devrait être possible d'implémenter dynamiquement une interface, par exemple donné:

public interface IFoo 
{
    string Bar(int baz);
}

public class Foo : IFoo
{
    public string Bar(int baz) { return baz.ToString(); }
}

public class Proxy : IDynamicMetaObjectProvider
{
    private readonly object target;

    public Proxy(object target) { this.target = target; }

    // something clever goes here
}

J'espère alors qu'il existe un moyen de permettre d'écrire:

dynamic proxy = new Proxy(new Foo());
IFoo fooProxy = (IFoo)proxy; // because the target object implements it
string bar = fooProxy.Bar(123); // delegates through to the target implementation

Mais, pour l'instant, je ne sais pas quoi remplacer // something clever goes here avec.

Donc, mes questions sont:

  1. Est-ce réellement possible avec le runtime dynamique? Il semble que l'implémentation dynamique de choses comme les méthodes et les propriétés soit assez facile, mais je n'ai trouvé aucune documentation sur l'implémentation dynamique des interfaces et des conversions vers celles-ci.

  2. En supposant que cela soit possible, à quel point est-ce difficile? (Vous pouvez supposer que je suis un programmeur décent avec une grande expérience de choses comme la réflexion, mais nouveau dans le cadre dynamique.)

  3. Existe-t-il des ressources qui pourraient m'aider à me diriger dans la bonne direction pour mettre en œuvre quelque chose comme ça? Ou même des échantillons où ce genre de chose a déjà été fait que je peux utiliser comme point de départ?

47
Greg Beech

Pour autant que je sache, il n'est pas possible sans intervention manuelle d'écrire ou de générer du code qui transmet les membres de l'interface à l'instance encapsulée. Si vous souhaitez voir le support fourni par Microsoft pour ce genre de chose, vous voudrez peut-être envisager de voter à https://connect.Microsoft.com/VisualStudio/feedback/details/526307/add-automatic-generation -of-interface-implementation-via-implementation-member .

13
Nicole Calinoiu

Le framework opensource Impromptu-Interface a été conçu pour cela. Il génère un proxy léger mis en cache avec une interface statique et utilise le dlr pour transmettre l'invocation à l'objet d'origine.

using ImpromptuInterface;

public interface ISimpeleClassProps
{
    string Prop1 { get;  }

    long Prop2 { get; }

    Guid Prop3 { get; }
}

-

dynamic tOriginal= new ExpandoObject();
tOriginal.Prop1 = "Test";
tOriginal.Prop2 = 42L;
tOriginal.Prop3 = Guid.NewGuid();

ISimpeleClassProps tActsLike = Impromptu.ActLike(tOriginal);
42
jbtule

Je pense que j'ai écrit une bibliothèque qui fait ce que vous voulez ... Elle s'appelle Dynamic Wrapper (sur CodePlex) et elle encapsulera automatiquement une classe pour implémenter une interface. Est-ce ce que vous voulez?

7
Brian Genisio

Le transtypage explicite, as et is échouent en raison de la comparaison de types avec votre classe de base proxy, mais le transtypage implicite peut déclencher DynamicObject.TryConvert, de sorte que vous pouvez ensuite renvoyer l'objet interne à la place de l'objet dynamique.
- Documentation MSDN TryConvert

Bien que le code ci-dessous fonctionne, ce n'est pas la délégation d'interface en soi, mais uniquement l'exposition de l'état interne. Il semble que vous recherchiez quelque chose comme un modèle d'interception tel que DynamicWrapper de Brian.

dynamic wrapper = new Proxy(new Foo());
IFoo foo = wrapper;
foo.Bar();

class Proxy : DynamicObject
{
    ...

    public override bool TryConvert(ConvertBinder binder, out object result)
    {
        Type bindingType = binder.Type;
        if (bindingType.IsInstanceOfType(target))
        {
            result = target;
            return true;
        }
        result = null;
        return false;

    }

}
3
stephbu

Complétant la réponse de @jbtule, j'ai créé mon CustomActivator qui est capable de créer un objet dynamique au moment de l'exécution et de le faire implémenter une interface souhaitée. J'utilise également le Impromptu-Interface framework pour accomplir cela.

L'appel est simple:

CustomActivator.CreateInstance<MyInterface>();

Je l'ai mis sur github .

2
fabriciorissetto