Access to derived class members

May 20, 2013 at 11:12 AM
I would like to access derived members of a CLR object, passed as reference to its base class but I do not know how. Executing following code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ClearScript.V8;

namespace TestDerivedObject
{
    class Base
    {
    }

    class Derived : Base
    {
        public Derived()
        {
            Test = "Test data";
        }

        public string Test { get; set; }
        public readonly string Foo = "Bar";
    }

    class Container
    {
        public Base Data { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var engine = new V8ScriptEngine())
            {
                engine.AllowReflection = true;
                engine.AddHostType("Container", typeof(Container));
                engine.AddHostType("Base", typeof(Base));
                engine.AddHostType("Derived", typeof(Derived));
                engine.AddHostType("Console", typeof(Console));
                var d = new Derived();
                var c = new Container();
                c.Data = d;
                Console.WriteLine(((Derived)c.Data).Foo);
                Console.WriteLine(((Derived)c.Data).Test);
                engine.Execute(@"
                    var d = new Derived();
                    var c = new Container();
                    c.Data = d;
                    Console.WriteLine(c.Data.Foo);
                    Console.WriteLine(c.Data.Test);
                ");
                Console.ReadLine();
            }
        }
    }
}
generates output
Bar
Test data
[undefined]
[undefined]
instead of desired
Bar
Test data
Bar
Test data
Is it possible to obtain a reference to derived object and how?
Coordinator
May 20, 2013 at 1:42 PM
Edited Aug 3, 2013 at 3:25 AM
Greetings and thank you for your question!

By default, ClearScript exposes a host member's declared type rather than its runtime type. This is important for correct method binding, among other things. The C# compiler does just the same (of course, it doesn't even know what the runtime type will be), and that's why you need the runtime cast to access the derived class members.

ClearScript's HostFunctions class allows you to perform the same cast in script:
using Microsoft.ClearScript;
then
engine.AddHostObject("host", new HostFunctions());
and then
engine.Execute(@"
    var d = new Derived();
    var c = new Container();
    c.Data = d;
    Console.WriteLine(host.cast(Derived, c.Data).Foo);
    Console.WriteLine(host.cast(Derived, c.Data).Test);
");
Another way, if you have control over the definition of Container, is to tell ClearScript to override its default behavior and expose the runtime type:
class Container
{
    [ScriptMember(ScriptMemberFlags.ExposeRuntimeType)]
    public Base Data { get; set; }
}
This way you won't need to perform the cast in script.

Thanks again, and please let us know if you have further questions!
Cheers!
May 20, 2013 at 1:48 PM
Thank you very much for prompt reply and for reply itself!