Pregunta

Actualmente estoy de alojamiento IronPython en una aplicación .NET 2.0.

Quiero crear una clase (en C #) cuyas instancias pueden ser "extendida" por el plugin de casos. Eso significa que, cada miembro de acceso que es insoluble en mi caso debe ser remitido a la instancia del complemento correspondiente que establezca ese miembro. Mi objetivo llevará a cabo un recipiente privado con aquellas instancias de plugins a continuación.

AFAICS, el camino a seguir no es a través de derivados de DynamicObject. El primer paso fue fácil hasta ahora que TryGetMember es llamada cuando utiliza el código Python miembros "desconocidos" de mi ejemplo. También podría devolver los objetos y los delegados que podrían utilizarse a partir del código Python.

Pero, de alguna manera, me quedé atrapado al intentar utilizar el DLR para realizar la "subsearch" en la instancia del complemento y e. G. devolver un método o una propiedad de la instancia del complemento en la forma IronPython lo espera.

¿Alguna pista son bienvenidos!

Gracias!

Edit: lo suficientemente clara mi pregunta original no fue formulada, lo siento. Aquí algunos puntos:

  • La solución tiene que correr con .NET llanura 2,0, no .NET 3.5 o 4.0 permiten animales.
  • La lista de conectores son por ejemplo (que significa cada instancia pueden tener una diferente - pero inmutable - lista de objetos Plugin)
  • .
  • Los objetos de plugin deben ser C # objetos plano con todos los miembros del público (o al menos los métodos y propiedades) mapeadas.
  • La detección de colisiones no es importante.

Gracias de nuevo.

¿Fue útil?

Solución

Lo que parece que usted quiere hacer es tener las instancias de plugin escrito al objeto o dinámica (en lugar de tener mecanografiados a alguna de las interfaces donde se pasa efectivamente a través de la solicitud TryGetMember) y luego realizar una unión contra otro objeto dinámico. Por suerte para usted el DLR interoperabilidad protocolo permite exactamente este escenario! Se va a requerir a bajar a la capa IDynamicMetaObjectProvider en lugar de utilizar DynamicObject pero en realidad es bastante simple. Te voy a mostrar un ejemplo sencillo usando InvokeMember que funciona de extremo a extremo w / C # 4.0. Tendrá que ir y hacer el resto de las operaciones - en particular, IronPython utilizará GetMember en lugar de InvokeMember. Pero eso es un proceso sencillo.

En primer lugar una explicación de cómo lo hace. A nivel IDMOP las ofertas DLR con objetos meta y lenguajes solicitar operaciones de objetos meta y los objetos meta vuelven más objetos meta. También puede pedir a la lengua para llevar a cabo la unión que de forma predeterminada y lo más importante que puede proporcionar a una sugerencia de qué hacer cuando las cosas van mal.

Con base en la que se puede pedir el lenguaje para tratar de obligar a cada uno de sus complementos y su propio objeto. Dependiendo de si se desea plugins para tener precedencia, o su objeto dinámico, se puede realizar la unión a ti mismo pasado. Este ejemplo muestra ambas técnicas basadas en los nombres de los miembros.

Así que sin más dilación, aquí está:

using System;
using System.Dynamic;
using System.Linq.Expressions;

namespace ConsoleApplication10 {
    class Program {
        static void Main(string[] args) {
            dynamic dynamicObj = new MyDynamicObject(new TestPlugin());
            dynamicObj.Foo();
            dynamicObj.Bar();
            Console.ReadLine();
        }

    }

    public class TestPlugin {
        public void Foo() {
            Console.WriteLine("TestPlugin Foo");
        }

        public void Bar() {
            Console.WriteLine("TestPlugin Bar");
        }
    }

    class MyDynamicObject : IDynamicMetaObjectProvider {
        internal readonly object[] _plugins;

        public void Foo() {
            Console.WriteLine("MyDynamicObject Foo");
        }

        public void Bar() {
            Console.WriteLine("MyDynamicObject Bar");
        }

        public MyDynamicObject(params object[] plugins) {
            _plugins = plugins;
        }

        class Meta : DynamicMetaObject {
            public Meta(Expression parameter, BindingRestrictions restrictions, MyDynamicObject self)
                : base(parameter, restrictions, self) {
            }

            public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) {                
                // get the default binding the language would return if we weren't involved
                // This will either access a property on MyDynamicObject or it will report
                // an error in a language appropriate manner.
                DynamicMetaObject errorSuggestion = binder.FallbackInvokeMember(this, args);

                // run through the plugins and replace our current rule.  Running through
                // the list forward means the last plugin has the highest precedence because
                // it may throw away the previous rules if it succeeds.
                for (int i = 0; i < Value._plugins.Length; i++) {
                    var pluginDo = DynamicMetaObject.Create(Value._plugins[i],
                        Expression.Call(
                            typeof(MyDynamicObjectOps).GetMethod("GetPlugin"),
                            Expression,
                            Expression.Constant(i)
                        )
                    );

                    errorSuggestion = binder.FallbackInvokeMember(pluginDo, args, errorSuggestion);                    
                }

                // Do we want DynamicMetaObject to have precedence?  If so then we can do
                // one more bind passing what we've produced so far as the rule.  Or if the
                // plugins have precedence we could just return the value.  We'll do that
                // here based upon the member name.

                if (binder.Name == "Foo") {
                    return binder.FallbackInvokeMember(this, args, errorSuggestion);
                }

                return errorSuggestion;
            }

            public new MyDynamicObject Value {
                get {
                    return (MyDynamicObject)base.Value;
                }
            }
        }



        #region IDynamicMetaObjectProvider Members

        public DynamicMetaObject GetMetaObject(System.Linq.Expressions.Expression parameter) {
            return new Meta(parameter, BindingRestrictions.Empty, this);
        }

        #endregion
    }

    public static class MyDynamicObjectOps {
        public static object GetPlugin(object myDo, int index) {
            return ((MyDynamicObject)myDo)._plugins[index];
        }
    }
}

Al ejecutar este grabados:

MyDynamicObject Foo TestPlugin Bar

Mostrando que los miembros de Foo preferimos la unión en el objeto real, y para los miembros Bar preferimos bar. Si se agrega el acceso a un tercer miembro Baz que produce C # 's de tiempo de ejecución excepción aglutinante. Si esto se llamó desde IronPython nos gustaría producir un AttributeError a programas de Python (un MissingMemberException en .NET) y un JavaScript en práctica debe devolver sin definir a sus programas.

Para que pueda obtener no sólo el sistema de plugins extensible también puede obtener fácilmente el comportamiento correcto en cualquier Langauge que consume su objeto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top