Mono 3.2 中与 Nancy Web 解决方案上的 DotLiquid 集合不一致的行为

本文关键字:DotLiquid 集合 不一致 解决方案 中与 Nancy Web Mono | 更新日期: 2023-09-27 18:37:25

在渲染液体模板时,在特定情况下,我在应用程序中看到了一些奇怪的不一致结果。作为记录,我使用的是Ubuntu 12.10,Mono 3.2.3和最新版本的Dotliquid(1.7)。我对 Dotliquid 进行了一些小的覆盖,我将在下面概述它们及其原因:

在DotLiquidViewEngine中,我插入了以下内容:

if (model is ResponseModel)
{
    hashedModel = new Hash((model as ResponseModel).ToHash());
}
else
{
    hashedModel = Hash.FromAnonymousObject(new
                  {
                      Model = new DynamicDrop(model),
                      ViewBag = new DynamicDrop(renderContext.Context.ViewBag)
                  });
}

这个微小变化的重点是,我不必键入 {{ model.myobject.property }},我可以改用 {{ myobject.property }}。

响应模型对象是一个字典。开始有点偏离快乐路径的部分是,我创建了一个继承自 DotLiquid.Drop 的对象,并且还实现了 IDictionary。通过这种方式,我可以通过 3 种不同的方式访问对象列表:

{{ mylist.list_item_key.property }}
{{ mylist["list_item_key"].property }}
{% foreach list in mylist %}
    {% if list.handle == 'list_item_key' %}
        {{ list.property }}
    {% endif %}
{% endfor %}

(我将在下面粘贴此通用集合代码。

看到的问题是:我提供的代码每次都可以在Windows环境中工作。在运行最新版本 Mono 的 Linux 托管环境中,此代码有时有效,有时则无效。

我能找到的唯一模式是,一旦 Apache 重新启动,无论第一个页面请求上发生什么(无论列表是否正确呈现),这种行为都会发生在每个后续页面请求中,直到我再次重新启动 Apache。当它失败时,只有上面列出的前两种方法失败了,第三种方法无论如何总是有效的。当我看到失败时,这是我看到的错误:

Liquid error: Array index is out of range. 

无论运行 Ubuntu 还是 CentOS,我在 Mono 中都会得到相同的不一致结果。我尝试在调试与发布模式下执行代码。我甚至尝试通过Visual Studio和Xamarin进行编译,看看它是否有帮助。无论如何,结果都是一样的。

唯一可能相关的其他信息是该解决方案在Nancy上运行,并且正在使用StructureMap进行IoC。这些都在Nuget的最新版本上。

我相当坚持这一点,所以任何见解都非常感谢。下面是实现 Drop 的泛型集合中的代码:

public class GenericCollectionDrop : Drop, IDictionary<string, object>
{
    private Dictionary<string, object> _collection = null;
    public GenericCollectionDrop()
    {
        _collection = new Dictionary<string, object>();
    }
    public override object BeforeMethod(string method)
    {
        if (this.ContainsKey(method))
            return this[method];
        return base.BeforeMethod(method);
    }
    public void Add(string key, object value)
    {
        _collection.Add(key, value);
    }
    public bool ContainsKey(string key)
    {
        return _collection.ContainsKey(key);
    }
    public ICollection<string> Keys
    {
        get { return _collection.Keys; }
    }
    public bool Remove(string key)
    {
        return _collection.Remove(key);
    }
    public bool TryGetValue(string key, out object value)
    {
        return _collection.TryGetValue(key, out value);
    }
    public ICollection<object> Values
    {
        get { return _collection.Values; }
    }
    public object this[string key]
    {
        get
        {
            return _collection[key];
        }
        set
        {
            _collection[key] = value;
        }
    }
    public void Add(KeyValuePair<string, object> item)
    {
        _collection.Add(item.Key, item.Value);
    }
    public void Clear()
    {
        _collection.Clear();
    }
    public bool Contains(KeyValuePair<string, object> item)
    {
        return _collection.Contains(item);
    }
    public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
    {
        throw new NotImplementedException();
    }
    public int Count
    {
        get { return _collection.Count; }
    }
    public bool IsReadOnly
    {
        get { return false; }
    }
    public bool Remove(KeyValuePair<string, object> item)
    {
        return _collection.Remove(item.Key);
    }
    public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
    {
        return _collection.GetEnumerator();
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return _collection.Values.GetEnumerator();
    }
}

我还尝试用这篇文章中提供的解决方案替换上面的类,结果相同:字典和 DotLiquid

Mono 3.2 中与 Nancy Web 解决方案上的 DotLiquid 集合不一致的行为

这是一个非常具体的问题,涉及一些尚未被广泛采用的开源组件,并且在大多数人会说不适合生产环境的平台上。我怀疑很多人会来寻找相同情况的答案,但我有一个解决方案,以防有人这样做:

我运行的DotLiquid版本是1.7。1.8 版(仍处于测试阶段)的注释看起来很有希望,我想我可以使用另一种解决方案来实现围绕安全接口模型的结果。但是,简单地将 DotLiquid 1.7 替换为 1.8 beta 似乎已经解决了这个问题,而无需对我进行任何代码更改。

就我个人而言,在我看来,唯一比不理解问题更糟糕的事情是不理解为什么特定问题被修复,所以也许将来我会挖掘源代码,看看下面发生了什么变化。目前,升级版本,甚至升级到测试版,已经完全消除了Linux/Apache/Mono中的问题,并且上述解决方案运行良好。