2010-06-04 26 views
38

Con las nuevas capacidades dinámicas en .NET 4.0, parece que debería ser posible implementar dinámicamente una interfaz, p. da:Implementación dinámica de una interfaz en .NET 4.0 (C#)

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 
} 

Entonces espero que haya alguna manera para que sea posible escribir:

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 

Pero, hasta ahora, estoy seguro de lo que para reemplazar // something clever goes here con.

Por lo tanto, mis preguntas son:

  1. Es esta realidad es posible que ver con el tiempo de ejecución dinámico? Parece que la implementación dinámica de cosas como métodos y propiedades es bastante fácil, pero no he encontrado ninguna documentación sobre la implementación dinámica de interfaces y conversiones.

  2. Suponiendo que esto sea posible, ¿qué tan difícil es? (Puede suponer que soy un programador decente con mucha experiencia en cosas como la reflexión, pero nuevo en el marco dinámico.)

  3. ¿Hay algún recurso que me ayude a orientarme en la dirección correcta para implementar algo como ¿esta? ¿O incluso muestras donde ya se ha hecho este tipo de cosas que puedo usar como punto de partida?

+0

¿De dónde vendrá el código que implementa los métodos de interfaz? –

Respuesta

13

Hasta donde yo sé, no es posible sin la intervención manual escribir o generar código que reenvía los miembros de la interfaz a la instancia envuelta. Si desea ver soporte proporcionado por Microsoft para este tipo de cosas, es posible que desee considerar votar al https://connect.microsoft.com/VisualStudio/feedback/details/526307/add-automatic-generation-of-interface-implementation-via-implementing-member .

+1

No se ha encontrado esta página de enlace ... –

+0

Creo que los comentarios se movieron a https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/2099133-add-auto-implement-feature-to- c-language pero eso cerrado. Las solicitudes de funciones de C# ahora deben ir a https://github.com/dotnet/csharplang –

7

creo que escribí una biblioteca que hace lo que quiere ... Se llama DynamicWrapper (en CodePlex) y se ajustará automáticamente una clase por lo que implementa una interfaz. Is this what you want?

+2

Es la misma idea, pero parece que su envoltura usa reflexión emitida? Eso es lo que estamos usando para hacer esto en este momento también, pero tengo curiosidad sobre si se podría hacer con el marco dinámico en lugar de tener que usar el reflejo emitido. –

3

conversión explícita, as y is fallan debido a la comparación de tipos sería en contra de su clase base proxy, pero conversión implícita puede desencadenar DynamicObject.TryConvert, de manera que a continuación, puede volver objeto interno en lugar del objeto dinámico.
- TryConvert MSDN Documentation

Mientras que el siguiente código funciona, esto no es delegación de interfaz per se, solo la exposición del estado interno. Parece que podría estar buscando algo así como un patrón de intercepción como Brian's DynamicWrapper.

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; 

    } 

} 
+0

+1, pero no las seguí: ¿por qué falla la conversión explícita? Es curioso porque 'ConvertBinder' tiene la propiedad' Explicit' para consultar eso. –

+0

Jordão parece que a diferencia de la sintaxis de conversión implícita que genera una llamada Binder.Convert en el IL generado, la sintaxis "is" y "as" omiten la prueba para la conversión. es decir, en el ejemplo q) claramente el tipo Foo! = tipo Proxy. – stephbu

38

El marco de código abierto Impromptu-Interface fue diseñado para hacer esto. Genera un proxy liviano en caché con una interfaz estática y utiliza el dlr para reenviar la invocación al objeto original.

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); 
+2

Qué gran marco. Me he encontrado usando esto a menudo. –

+2

+1: biblioteca impresionante – IAbstract

2

Como complemento a la respuesta de @jbtule He creado mi CustomActivator que es capaz de crear un objeto dinámico en tiempo de ejecución y hacer que implementa una interfaz deseada. También utilizo el Impromptu-Interface framework para lograr eso.

La llamada es simple:

CustomActivator.CreateInstance<MyInterface>(); 

lo puse en github.

Cuestiones relacionadas