Непоследовательное поведение в Mono 3.2 с коллекциями DotLiquid в Nancy Web Solution

Я вижу некоторые странно противоречивые результаты в моем приложении при определенных обстоятельствах при выводе жидкого шаблона. Для справки, я нахожусь на 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 }}.

Объект ResponseModel - это словарь. Часть, которая начинает немного отклоняться от счастливого пути, состоит в том, что я создал объект, который наследуется от DotLiquid.Drop, а также реализует IDictionary. Таким образом, я могу получить доступ к списку объектов тремя различными способами:

{{ 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. В среде хостинга Linux, работающей под управлением последней версии Mono, этот код иногда работает, а иногда нет.

Единственный шаблон, который я могу найти, это то, что после перезапуска Apache, что бы ни происходило при запросе первой страницы (независимо от того, правильно ли отображаются списки), такое поведение будет происходить при каждом последующем запросе страницы, пока я снова не перезапущу Apache. Когда это терпит неудачу, только первые два подхода, перечисленные выше, терпят неудачу, третий подход всегда работает, несмотря ни на что. Когда я вижу сбой, я вижу эту ошибку:

Liquid error: Array index is out of range. 

Я получаю одинаковые противоречивые результаты в Mono независимо от того, работает ли Ubuntu или CentOS. Я попытался выполнить код в режиме отладки против выпуска. Я даже пытался скомпилировать через 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.

1 ответ

Решение

Это очень специфический вопрос, касающийся нескольких компонентов с открытым исходным кодом, которые еще не получили широкого распространения, и о платформе, которая, по мнению большинства людей, не подходит для производственной среды. Я сомневаюсь, что многие люди придут в поисках ответа на эту же ситуацию, но у меня есть решение, если кто-нибудь сделает:

Я использую версию DotLiquid 1.7. Примечания к версии 1.8 (все еще в бета-версии) выглядели многообещающе, и я решил, что смогу найти другое решение для достижения результатов, связанных с безопасными моделями интерфейсов. Однако простая замена DotLiquid 1.7 на 1.8 beta, похоже, решила проблему без необходимости вносить какие-либо изменения в мой код.

Лично, на мой взгляд, единственное, что хуже, чем не понимать проблему, это не понять, почему конкретная проблема решена, так что, возможно, в будущем я покопаюсь в источнике и посмотрю, что изменилось под ним. На данный момент обновление версии, даже до бета-версии, полностью устранило проблему в Linux/Apache/Mono, и вышеприведенное решение прекрасно работает.

Другие вопросы по тегам