|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Linq.Expressions;
using System.Reflection;
namespace Microsoft.AspNetCore.Mvc.ViewFeatures;
internal readonly struct MemberExpressionCacheKey
{
public MemberExpressionCacheKey(Type modelType, MemberExpression memberExpression)
{
ModelType = modelType;
MemberExpression = memberExpression;
Members = null;
}
public MemberExpressionCacheKey(Type modelType, MemberInfo[] members)
{
ModelType = modelType;
Members = members;
MemberExpression = null;
}
// We want to avoid caching a MemberExpression since it has references to other instances in the expression tree.
// We instead store it as a series of MemberInfo items that comprise of the MemberExpression going from right-most
// expression to left.
public MemberExpressionCacheKey MakeCacheable()
{
var members = new List<MemberInfo>();
foreach (var member in this)
{
members.Add(member);
}
return new MemberExpressionCacheKey(ModelType, members.ToArray());
}
public MemberExpression MemberExpression { get; }
public Type ModelType { get; }
public MemberInfo[] Members { get; }
public Enumerator GetEnumerator() => new Enumerator(this);
public struct Enumerator
{
private readonly MemberInfo[] _members;
private int _index;
private MemberExpression _memberExpression;
public Enumerator(in MemberExpressionCacheKey key)
{
Current = null;
_members = key.Members;
_memberExpression = key.MemberExpression;
_index = -1;
}
public MemberInfo Current { get; private set; }
public bool MoveNext()
{
if (_members != null)
{
_index++;
if (_index >= _members.Length)
{
return false;
}
Current = _members[_index];
return true;
}
if (_memberExpression == null)
{
return false;
}
Current = _memberExpression.Member;
_memberExpression = _memberExpression.Expression as MemberExpression;
return true;
}
}
}
|