scriban/scriban

Does Scriban support .NET Object Indexers ?

CADbloke opened this issue · 3 comments

Firstly, thanks for this awesome library. I am investigating using it in an app that will retrieve data for CAD drawings of wiring diagrams for television stations, just in case you thought you'd heard every use-case.

My question: does the .NET object property retrieval support class indexers like Thing["Index"] where Index isn't an actual property but rather the argument for an indexer lookup? For a MSFT example on indexers - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/indexers/using-indexers#example-2

cheers

I think I can answer my own question here: "not yet" and "looks tricky". Or it does and I missed it,

Looking at https://github.com/lunet-io/scriban/blob/63ad634ffaf55cd4b8e72d1342f979520934c5be/src/Scriban/Runtime/Accessors/TypedObjectAccessor.cs at TryGetValue is only looks up fields and properties.

I found https://stackoverflow.com/questions/14462820/check-if-indexing-operator-exists/14462921#14462921 for reference on indexers and how to find it.

related: #116

I tried adding this code to TryGetValue ...

var indexer = _type.GetProperties().FirstOrDefault(p => p.GetIndexParameters().Length != 0
                                                      && !typeof(IList).IsAssignableFrom(_type));

if (indexer != null)
{
    object[] indexArgs = { member };

    try
    {
        value = indexer.GetValue(target, indexArgs);
    }
    catch (Exception )
    {
        return false;
    }
    return true;
}

return false;

but it broke .NET standard v1 & it also bypasses any filters etc. so it's not pull-request worthy.

Severity	Code	Description	Project	File	Line	Suppression State
Error	CS1061	'Type' does not contain a definition for 'GetProperties' and no accessible extension method 'GetProperties' accepting a first argument of type 'Type' could be found (are you missing a using directive or an assembly reference?)	Scriban(netstandard1.1), Scriban(netstandard1.3)	D:\CodezOnD\Github\scriban\src\Scriban\Runtime\Accessors\TypedObjectAccessor.cs	63	Active

I added this test to https://github.com/lunet-io/scriban/blob/548998cbebb27534dcd36526ab0f2535ea81c237/src/Scriban.Tests/TestRuntime.cs (at line 730)

[Test]
        public void TestIndexerOnNETwithIndex()
        {
            var myobject = new MyObjectHasIndexer() { FieldA = "yo"};
            var result   = Template.Parse("{{obj['xxx']}}").Render(new ScriptObject() {{"obj", myobject}});
            Assert.AreEqual("found", result);
        }

        private class MyObjectHasIndexer : MyStaticObject
        {
            public string FieldA;

            public string FieldB;

            public string PropertyA { get; set; }

            public string PropertyB { get; set; }

            public string this[string key]
            {
                get
                {
                    if (key == "xxx")
                        return "found";

                    return null;
                }
                set{}
            }
        }

and it passed in .NET 3.5. but everything else seems broken. Oops

Your thoughts?

xoofx commented

The commit 14b0b17 should fix this issue. it will be part of the next release

Thank you!

Sorry about my delay in responding. This is much appreciated. I will put together some tests of the way I plan to implement it and let you know how I go. It will probably me a couple of months before I have my shit together but this definitely opens up a lot of possibilities.

Thanks again
Ewen