public T Get(object target) { T value; while (!mCachedTryGet(target, out value)) { mCachedType = target.GetType(); mCachedTryGet = BuildCachedTryGet(MethodName, mCachedType); } return(value); }
public T Get(object target) { T value; while (!TryGet(target, out value)) { mCachedTypes.RemoveAt(mCachedTypes.Count - 1); mCachedTypes.Insert(0, target.GetType()); mCachedTryGet = BuildCachedTryGet(MethodName, mCachedTypes); } return(value); }
public bool TryGet(object target, out T result) { while (true) { if (mCachedTryGet(target, out result)) { return(true); } if (mCachedTypes.Count >= kMaxCachedTypes) { return(false); } mCachedTypes.Add(target.GetType()); mCachedTryGet = BuildCachedTryGet(MethodName, mCachedTypes); } }
public MonomorphicCache(string methodName, Type targetType) { MethodName = methodName; mCachedType = targetType; mCachedTryGet = BuildCachedTryGet(MethodName, mCachedType); }
public PolymorphicCache(string methodName, IEnumerable <Type> targetTypes) { MethodName = methodName; mCachedTypes.AddRange(targetTypes); mCachedTryGet = BuildCachedTryGet(MethodName, mCachedTypes); }
private static IReadOnlyList <T> GetPossibleTs <T>( SourceSymbolContext context, QualifiedName name, ImmutableArray <IType> typeArguments, TryGetT <T> tryGetT, GetLocalTs <T> getLocalTs, GetFullyQualifiedName <T> getFullyQualifiedName, GetTypeParameters <T> getTypeParameters) where T : class { List <T> possibleTs; if (name.Parent is null) { // local ts have priority over top level ts, // and an inner local t hides an outer local t // local ts can only have simple names, so we can skip this check if the name is not simple var scope = context.Scope; while (scope != null) { possibleTs = getLocalTs(scope) .Where( x => getFullyQualifiedName(x) == name && getTypeParameters(x).Length == typeArguments.Length) .ToList(); if (possibleTs.Count > 0) { return(possibleTs); } scope = scope.DeclaringMethod; } } var assemblies = context.Assembly.ReferencedAssembliesAndSelf; // types in the innermost namespace have priority over types in its parent namespace, // which have priority over types in its parent etc. var @namespace = context.NameSpace; while (@namespace != null) { var possibleName = name.Prepend(@namespace); possibleTs = LookupPossibleName(possibleName).ToList(); if (possibleTs.Count > 0) { return(possibleTs); } @namespace = @namespace?.Parent; } // Types in the global namespace have priority over types defined in imports possibleTs = LookupPossibleName(name).ToList(); if (possibleTs.Count > 0) { return(possibleTs); } // look for types in imports if (name.Parent is null) { // imports only bring the top level types into scope, so they are only relevant if the name is simple; var possibleNames = context.Imports.Select(x => x.Append(name)).ToList(); return (possibleNames .SelectMany(LookupPossibleName) .ToList()); } return(Array.Empty <T>()); IEnumerable <T> LookupPossibleName(QualifiedName possibleName) { return(assemblies.Select(x => { tryGetT(x, possibleName, out var t); return t; }).Where(x => x != null && getTypeParameters(x).Length == typeArguments.Length) !); } }