質問

I'm writing a Javascript <-> C# bridge and ran into the following problem:

There's a class JSObject:

public class JSObject : DynamicObject
{
    public JSEngineAPI wrappedObject { get; set; }

    public JSObject(JSEngineAPI WrappedObject);
    public override bool TryConvert(ConvertBinder binder, out object result);
    public override bool TryGetMember(GetMemberBinder binder, out object result);
    ...
}

and let's assume there's a simple test case like

public class TestClass
{
    public string message = "This is a C# string";
}

public class TestApp
{
    public string testComplexObject(TestClass obj)
    {
        return obj.message;
    }
}

Now I want to be able to do

JSObject jsObj = ...;
string message = testComplexObject(jsObj);

Doing obj.message should perform a TryGetMember() call. Effectively the jsObj should pretend to be a TestClass instance. Note that the call to testComplexObject is just an example, later I need to be able to support calling arbitrary functions with arbitrary arguments.

I've tried various ways to make this work, but none of them worked. So I wonder about a good way to achieve this.

I've thought about creating a class at runtime which inherits from TestClass. This dynamic class will contain generated members which overload their base class pendants. Each of these methods would forward to the JSObject/JSEngineAPI to perform the real work. Then I could pass an instance of this dynamic class into the testComplexObject method.

However this sounds rather involved and I'd love to know if there are easier/other approaches to this.

EDIT #1: I guess if you take away the "DynamicObject" part this question is a bit like how can I create a proxy for type T at runtime?

EDIT #2: I've also looked into RealProxy and IDynamicMetaObjectProvider now and wonder if these are of any help.

Thanks for your time, -Matthias

役に立ちましたか?

解決

As the signature of the method cannot be changed, you could create a proxy to stand in for your dynamic object. This will be effective only if the objects are PODs or you stick to virtual methods that you could override. Otherwise your methods could end up not being used. It will implement the the desired type but will pass all accesses to your actual object. Using this will be easy if you add some conversion methods to your dynamic object. Something like this:

public class JSObject : DynamicObject
{
    class TestClassProxy : TestClass
    {
        private dynamic wrapper;
        public TestClassProxy(dynamic obj)
        {
            wrapper = obj;
            // assign copies of the fields
            message = obj.message;
        }
        // override all required methods and properties
        public override void SampleMethod()
        {
            wrapper.SampleMethod();
        }
        public override int SomeValue
        {
            get { return wrapper.SomeValue; }
            set { wrapper.SomeValue = value; }
        }
        // etc...
    }

    public override bool TryConvert(ConvertBinder binder, out object result)
    {
        if (binder.Type == typeof(TestClass))
        {
            result = new TestClassProxy(this);
            return true;
        }
        // your other conversions
        return base.TryConvert(binder, out result);
    }
    // etc...
}

If you need to do more with your objects, I don't know how else you could get around this other than changing the method's signature.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top