Liquid テンプレートをレンダリングする際に、特定の状況下でアプリケーションに奇妙に一貫性のない結果が表示されます。記録のために、私は 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 も実装するオブジェクトを作成したことです。このようにして、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 を再起動するまで、後続のすべてのページ要求でこの動作が発生するということです。失敗した場合、失敗するのは上記の最初の 2 つのアプローチだけであり、3 番目のアプローチは常に機能します。失敗すると、次のエラーが表示されます。
Liquid error: Array index is out of range.
Ubuntu または CentOS の実行に関係なく、Mono で同じ一貫性のない結果が得られます。コードをデバッグ モードとリリース モードで実行してみました。Visual Studio と Xamarin でコンパイルして、役立つかどうかを確認しました。何をしても同じ結果。
関連する可能性のある他の唯一の情報は、ソリューションが Nancy で実行され、IoC に StructureMap を使用していることです。これらは両方とも 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();
}
}
上記のクラスを、この投稿で提供されている解決策で同じ結果に置き換えてみました: Dictionaries and DotLiquid