开发者

Make a DataRow class that implements ILiquidizable

开发者 https://www.devze.com 2023-01-30 18:33 出处:网络
I\'m trying to use Dot Liquid which is one of the coolest templating engines for c#. Dot Liquid uses a way in order to make using templates safe. Here is the explanation page.

I'm trying to use Dot Liquid which is one of the coolest templating engines for c#. Dot Liquid uses a way in order to make using templates safe. Here is the explanation page.

Here is the Explanation from it's wiki:

DotLiquid, by default, only accepts a limited number of types as parameters to the Render method - including the .NET primitive types(int, float, string, etc.), and some collection types including IDictionary, IList and IIndexable (a custom DotLiquid interface).

If it supported arbitrary types, then it could result in properties or methods being unintentionally exposed to template authors. To prevent this, DotLiquid uses Drop objects. Drops use an opt-in approach to开发者_开发百科 exposing object data.

The Drop class is just one implementation of ILiquidizable, and the simplest way to expose your objects to DotLiquid templates is to implement ILiquidizable directly

Wiki Sample Code:

public class User
{
    public string Name { get; set; }
    public string Email { get; set; }
}

public class UserDrop : Drop
{
    private readonly User _user;

    public string Name
    {
        get { return _user.Name; }
    }

    public UserDrop(User user)
    {
        _user = user;
    }
}

Template template = Template.Parse("Name: {{ user.name }}; Email: {{ user.email }};");
string result = template.Render(Hash.FromAnonymousObject(new
{
    user = new UserDrop(new User
    {
        Name = "Tim",
        Email = "me@mydomain.com"
    })
}));

So when I pass DataRow to liquid, liquid wont let me show it's content and tells me that:

'System.Data.DataRow' is invalid because it is neither a built-in type nor implements ILiquidizable

Is there any solutions to pass DataRow object that implements ILiquidizable too? Thanks


As marc_s indicated, you'll need to convert the DataRow object to your own class instance, or at least wrap it with your own class instance. I'd suggest wrapping it like this:

internal class DataRowDrop : Drop
{
    private readonly DataRow _dataRow;

    public DataRowDrop(DataRow dataRow)
    {
        _dataRow = dataRow;    
    }

    public override object BeforeMethod(string method)
    {
        if (_dataRow.Table.Columns.Contains(method))
            return _dataRow[method];
        return null;
    }
}

Sample usage would be:

[Test]
public void TestDataRowDrop()
{
    DataTable dataTable = new DataTable();
    dataTable.Columns.Add("Column1");
    dataTable.Columns.Add("Column2");

    DataRow dataRow = dataTable.NewRow();
    dataRow["Column1"] = "Hello";
    dataRow["Column2"] = "World";

    Template tpl = Template.Parse(" {{ row.column1 }} ");
    Assert.AreEqual(" Hello ", tpl.Render(Hash.FromAnonymousObject(new
    {
        row = new DataRowDrop(dataRow)
    })));
}

I've also added this example drop class, and the corresponding unit test, to the unit tests for DotLiquid drops.

0

精彩评论

暂无评论...
验证码 换一张
取 消