Replace an instance of a .NET object with an IronPython object

I am trying to do the following:

  • Get an instance of an object defined in C #
    • It implements a specific interface.
    • This field is on another instance of a C # class
  • Wrap it with an IronPython proxy that logs method calls
  • Place a wrapper instead of the original object

Here is an example showing what I'm trying to do. In fact, the interface IWoofhas many other methods on it.

C # classes and interface:

namespace Foo
{
    public interface IWoof { string DoSomething(); }

    public class Bar
    {
        public Bar() { Woof = new WoofImp(); }
        public IWoof Woof { get; set; }
    }

    public class WoofImp : IWoof
    {
        public string DoSomething()
        {
            return "DoSomething executing in C#";
        }
    }

}

I want to take bar.Woofand replace it with IronPython proxy. I want to do this with IronPython Script. I have tried different things.

First try: getattr override

I defined Wrapper as follows:

class Wrapper(object):

    def __init__(self, obj):
        self._obj = obj

    def __getattr__(self, name):
        print '__getattr__ called'
        if name == "DoSomething":
           return self.__DoSomething
        else:
            return object.__getattr__(self, name)

    def __DoSomething(self):
        result = self._obj.DoSomething()
        return result + " AND DoSomething executing in Python"

This works great, as you would expect:

import Foo
bar = Foo.Bar()
woof = Wrapper(bar.Woof)
print woof.DoSomething()

> DoSomething executing in C# AND DoSomething executing in Python

, bar.Woof , :

bar.Woof = woof_wrapper

> TypeError: expected IWoof, got Object_1$1
> Microsoft.Scripting.ArgumentTypeException: expected IWoof, got Object_1$1
   at CallSite.Target(Closure , CallSite , Object , Object )
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
   at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)

: #

, , IWoof, .

class Wrapper_IWoof(object, Foo.IWoof): # Inherits from IWoof
... etc

:

woof = Wrapper_IWoof(bar.Woof)
bar.Woof = woof
print bar.Woof.DoSomething()

:

> AttributeError: 'Wrapper_IWoof' object has no attribute 'DoSomething'
> System.MissingMemberException: 'Wrapper_IWoof' object has no attribute 'DoSomething'
   at IronPython.Runtime.Operations.PythonOps.MissingInvokeMethodException(Object o, String name)
   at IronPython.NewTypes.System.Object#IWoof_4$4.DoSomething()
   at Microsoft.Scripting.Interpreter.FuncCallInstruction`2.Run(InterpretedFrame frame)
   at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
   at Microsoft.Scripting.Interpreter.LightLambda.Run3[T0,T1,T2,TRet](T0 arg0, T1 arg1, T2 arg2)
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
   at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)

:

( IWoof): http://www.ronnie-midnight-oil.net/2008/11/checking-type-contract-from-ironpython.html , .

- python . , . , .

, , . - - ?

+4
1

, __getattr__. :

class Wrapper_IWoof(object, Foo.IWoof):

    def __init__(self, obj):
        self._obj = obj

    def DoSomething(self):
        result = self._obj.DoSomething()
        return result + " AND DoSomething executing in Python"
0

Source: https://habr.com/ru/post/1531556/


All Articles