public void SimplePropertyAccess_GetCustomMember()
        {
            const string scriptFunctionSourceCode = @"
import clr
def PropertyPathAccess(cascade) :
  return cascade.Child.Child.Child.Child.Child.Child.Child.Child.Child.Name
";

            const int numberChildren = 10;
            var       cascadeWithoutStableBinding = new Cascade(numberChildren);
            var       cascadeStableBinding        = new CascadeStableBinding(numberChildren);

            var privateScriptEnvironment = ScriptEnvironment.Create();

            privateScriptEnvironment.Import(typeof(TestDomain.Cascade).Assembly.GetName().Name, typeof(TestDomain.Cascade).Namespace, typeof(TestDomain.Cascade).Name);

            var propertyPathAccessScript = new ScriptFunction <Cascade, string> (
                _scriptContext, ScriptLanguageType.Python,
                scriptFunctionSourceCode, privateScriptEnvironment, "PropertyPathAccess"
                );

            //var nrLoopsArray = new[] { 1, 1, 10000 };
            var nrLoopsArray = new[] { 1, 1, 100000 };

            // Warm up
            ScriptingHelper.ExecuteAndTime(nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeStableBinding)).Last();

            double timingStableBinding        = ScriptingHelper.ExecuteAndTime(nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeStableBinding)).Last();
            double timingWithoutStableBinding = ScriptingHelper.ExecuteAndTime(nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeWithoutStableBinding)).Last();

            //To.ConsoleLine.e (() => timingStableBinding).e (() => timingWithoutStableBinding);
            //To.ConsoleLine.e ("timingStableBinding / timingWithoutStableBinding = ", timingStableBinding / timingWithoutStableBinding);

            Assert.That(timingStableBinding / timingWithoutStableBinding, Is.LessThan(7.0));
        }
        public void SimplePropertyAccess_GetCustomMember2()
        {
            const string scriptFunctionSourceCode = @"
import clr
def PropertyPathAccess(cascade) :
  return cascade.Child.Child.Child.Child.Child.Child.Child.Child.Child.Name
";

            const int numberChildren                = 10;
            var       cascade                       = new Cascade(numberChildren);
            var       cascadeStableBinding          = new CascadeStableBinding(numberChildren);
            var       cascadeStableBindingFromMixin = ObjectFactory.Create <CascadeStableBindingFromMixin> (ParamList.Create(numberChildren));

            var privateScriptEnvironment = ScriptEnvironment.Create();

            privateScriptEnvironment.Import(typeof(TestDomain.Cascade).Assembly.GetName().Name, typeof(TestDomain.Cascade).Namespace, typeof(TestDomain.Cascade).Name);

            var propertyPathAccessScript = new ScriptFunction <Cascade, string> (
                _scriptContext, ScriptLanguageType.Python,
                scriptFunctionSourceCode, privateScriptEnvironment, "PropertyPathAccess"
                );

            var nrLoopsArray = new[] { 1, 1, 100000 };

            ScriptingHelper.ExecuteAndTime("SimplePropertyAccess_GetCustomMember2 (No StableBinding)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascade));
            ScriptingHelper.ExecuteAndTime("SimplePropertyAccess_GetCustomMember2 (StableBinding from Mixin)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeStableBindingFromMixin));
            ScriptingHelper.ExecuteAndTime("SimplePropertyAccess_GetCustomMember2 (StableBinding)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeStableBinding));
        }
        public void LongPropertyPathAccess_StableBinding()
        {
            const string scriptFunctionSourceCode =
                @"
import clr
def PropertyPathAccess(cascade) :
  if cascade.GetChild().GetChild().GetChild().GetChild().GetChild().GetChild().GetChild().GetChild().GetChild().GetName() == 'C0' :
    return cascade.GetChild().GetChild().GetChild().GetChild().GetChild().GetChild().GetChild().GetName()
  return 'FAILED'
";

            const int numberChildren       = 10;
            var       cascade              = new Cascade(numberChildren);
            var       cascadeStableBinding = new CascadeStableBinding(numberChildren);
            //var cascadeStableBinding = ObjectFactory.Create<CascadeStableBinding> (ParamList.Create (numberChildren));

            var privateScriptEnvironment = ScriptEnvironment.Create();

            privateScriptEnvironment.Import(typeof(Cascade).Assembly.GetName().Name, typeof(Cascade).Namespace, typeof(Cascade).Name);

            var propertyPathAccessScript = new ScriptFunction <Cascade, string> (
                _scriptContext,
                ScriptLanguageType.Python,
                scriptFunctionSourceCode,
                privateScriptEnvironment,
                "PropertyPathAccess"
                );

            //var nrLoopsArray = new[] { 1, 1, 10, 100, 1000, 10000, 100000, 1000000 };
            var nrLoopsArray = new[] { 1, 1, 10, 100, 1000, 10000 };

            ScriptingHelper.ExecuteAndTime("script function", nrLoopsArray, () => propertyPathAccessScript.Execute(cascade));
            ScriptingHelper.ExecuteAndTime("script function (stable binding)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeStableBinding));
        }
 public CascadeStableBinding(int nrChildren)
 {
     --nrChildren;
     _name = "C" + nrChildren;
     if (nrChildren > 0)
     {
         Child = new CascadeStableBinding(nrChildren);
     }
 }
        public void LongPropertyPathAccess_StableBindingSimple()
        {
            const string scriptFunctionSourceCode = @"
import clr
def PropertyPathAccess(cascade) :
  return cascade.GetChild().GetChild().GetName()
";

            const int numberChildren       = 10;
            var       cascade              = new Cascade(numberChildren);
            var       cascadeStableBinding = new CascadeStableBinding(numberChildren);
            //var cascadeStableBinding = ObjectFactory.Create<CascadeStableBinding> (ParamList.Create (numberChildren));
            var cascadeLocalStableBinding = new CascadeLocalStableBinding(numberChildren);

            var cascadeGetCustomMemberReturnsAttributeProxyFromMap = new CascadeGetCustomMemberReturnsAttributeProxyFromMap(numberChildren);

            cascadeGetCustomMemberReturnsAttributeProxyFromMap.AddAttributeProxy("GetChild", cascade, _scriptContext);
            cascadeGetCustomMemberReturnsAttributeProxyFromMap.AddAttributeProxy("GetName", cascade, _scriptContext);


            var privateScriptEnvironment = ScriptEnvironment.Create();

            privateScriptEnvironment.Import(typeof(Cascade).Assembly.GetName().Name, typeof(Cascade).Namespace, typeof(Cascade).Name);

            var propertyPathAccessScript = new ScriptFunction <Cascade, string> (
                _scriptContext,
                ScriptLanguageType.Python,
                scriptFunctionSourceCode,
                privateScriptEnvironment,
                "PropertyPathAccess"
                );


            privateScriptEnvironment.ImportIifHelperFunctions();
            privateScriptEnvironment.SetVariable("GLOBAL_cascade", cascade);
            var expression = new ExpressionScript <Object> (
                _scriptContext,
                ScriptLanguageType.Python,
                "GLOBAL_cascade.GetChild().GetChild().GetName()",
                privateScriptEnvironment
                );


            //var nrLoopsArray = new[] { 1, 1, 10, 100, 1000, 10000, 100000, 1000000 };
            var nrLoopsArray = new[] { 1, 1, 10, 100, 1000, 10000 };

            ScriptingHelper.ExecuteAndTime("script function", nrLoopsArray, () => propertyPathAccessScript.Execute(cascade));
            ScriptingHelper.ExecuteAndTime("script function (stable binding)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeStableBinding));
            ScriptingHelper.ExecuteAndTime("script function (local stable binding)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeLocalStableBinding));
            ScriptingHelper.ExecuteAndTime("script function (from map)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeGetCustomMemberReturnsAttributeProxyFromMap));
        }
        public void SimplePropertyAccess_GetCustomMember()
        {
            const string scriptFunctionSourceCode = @"
import clr
def PropertyPathAccess(cascade) :
  return cascade.Name
";

            const int numberChildren = 10;
            var       cascade        = new Cascade(numberChildren);
            //var cascadeStableBinding = ObjectFactory.Create<CascadeStableBinding> (ParamList.Create (numberChildren));
            var cascadeStableBinding   = new CascadeStableBinding(numberChildren);
            var cascadeGetCustomMember = new CascadeGetCustomMemberReturnsString(numberChildren);

            var attributeNameProxy = _scriptContext.GetAttributeProxy(cascade, "Name");
            var cascadeGetCustomMemberReturnsFixedAttributeProxy = new CascadeGetCustomMemberReturnsFixedAttributeProxy(numberChildren, attributeNameProxy);


            var privateScriptEnvironment = ScriptEnvironment.Create();

            privateScriptEnvironment.Import(typeof(Cascade).Assembly.GetName().Name, typeof(Cascade).Namespace, typeof(Cascade).Name);

            var propertyPathAccessScript = new ScriptFunction <Cascade, string> (
                _scriptContext,
                ScriptLanguageType.Python,
                scriptFunctionSourceCode,
                privateScriptEnvironment,
                "PropertyPathAccess"
                );

            //var nrLoopsArray = new[] { 1, 1, 10, 100, 1000, 10000, 100000, 1000000 };
            var nrLoopsArray = new[] { 1, 1, 10, 100, 1000, 10000, 100000 };

            ScriptingHelper.ExecuteAndTime("script function", nrLoopsArray, () => propertyPathAccessScript.Execute(cascade));
            ScriptingHelper.ExecuteAndTime("script function (stable binding)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeStableBinding));
            ScriptingHelper.ExecuteAndTime("script function (GetCustomMember)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeGetCustomMember));
            ScriptingHelper.ExecuteAndTime("script function (GetCustomMember)", nrLoopsArray, () => propertyPathAccessScript.Execute(cascadeGetCustomMemberReturnsFixedAttributeProxy));
        }