C # Преобразование DynamicObject в произвольный тип - PullRequest
3 голосов
/ 29 марта 2011

Я пишу мост Javascript <-> C # и столкнулся со следующей проблемой:

Есть класс 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);
    ...
}

и давайте предположим, что есть простой тестовый пример, такой как

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

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

Теперь я хочу быть в состоянии сделать

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

Выполнение obj.message должно выполнить вызов TryGetMember(). По сути, jsObj должен выдавать себя за экземпляр класса TestClass. Обратите внимание, что вызов testComplexObject является только примером, позже мне нужно иметь возможность поддерживать вызов произвольных функций с произвольными аргументами.

Я пробовал разные способы заставить это работать, но ни один из них не работал. Поэтому мне интересно найти хороший способ добиться этого.

Я думал о создании класса во время выполнения, который наследуется от TestClass. Этот динамический класс будет содержать сгенерированные члены, которые перегружают их подвески базового класса. Каждый из этих методов направляет JSObject / JSEngineAPI для выполнения реальной работы. Затем я мог бы передать экземпляр этого динамического класса в метод testComplexObject.

Однако это звучит довольно сложно, и я хотел бы знать, есть ли более простые / другие подходы к этому.

РЕДАКТИРОВАТЬ # 1: Я думаю, если вы уберете часть "DynamicObject", этот вопрос будет немного похож на то, как я могу создать прокси для типа T во время выполнения?

РЕДАКТИРОВАТЬ # 2: Я также изучил RealProxy и IDynamicMetaObjectProvider и спрашиваю себя, помогают ли они.

Спасибо за ваше время, -Matthias

1 Ответ

3 голосов
/ 29 марта 2011

Поскольку подпись метода не может быть изменена, вы можете создать прокси-сервер для замены вашего динамического объекта.Это будет эффективно только в том случае, если объекты являются POD или вы используете виртуальные методы, которые вы можете переопределить.В противном случае ваши методы могут оказаться неиспользованными.Он реализует нужный тип, но передаст все обращения к вашему фактическому объекту.Использовать это будет легко, если вы добавите несколько методов преобразования в ваш динамический объект.Примерно так:

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...
}

Если вам нужно сделать больше с вашими объектами, я не знаю, как еще вы могли бы обойти это, кроме изменения сигнатуры метода.

...