public BaseTest() { HttpContext.Current = new HttpContext( new HttpRequest(string.Empty, "http://tempuri.org", string.Empty), new HttpResponse(new StringWriter()) ); ProcessStorage <string, CacheItem> .Clear(); }
protected void SetupValidator(ModelMetadata metadata) { var fieldId = $"{metadata.ContainerType.FullName}.{metadata.PropertyName}".ToLowerInvariant(); AttributeFullId = $"{Attribute.TypeId}.{fieldId}".ToLowerInvariant(); AttributeWeakId = $"{typeof(T).FullName}.{fieldId}".ToLowerInvariant(); var item = ProcessStorage <string, CacheItem> .GetOrAdd(AttributeFullId, _ => // map cache is based on static dictionary, set-up once for entire application instance { // (by design, no reason to recompile once compiled expressions) IDictionary <string, Expression> fields = null; Attribute.Compile(metadata.ContainerType, parser => { fields = parser.GetFields(); FieldsMap = fields.ToDictionary(x => x.Key, x => Helper.GetCoarseType(x.Value.Type)); ConstsMap = parser.GetConsts(); EnumsMap = parser.GetEnums(); MethodsList = parser.GetMethods(); }); // compile the expression associated with attribute (to be cached for subsequent invocations) AssertClientSideCompatibility(); ParsersMap = fields .Select(kvp => new { FullName = kvp.Key, ParserAttribute = (kvp.Value as MemberExpression)?.Member.GetAttributes <ValueParserAttribute>().SingleOrDefault() }).Where(x => x.ParserAttribute != null) .ToDictionary(x => x.FullName, x => x.ParserAttribute.ParserName); if (!ParsersMap.ContainsKey(metadata.PropertyName)) { var currentField = metadata.ContainerType .GetProperties().Single(p => metadata.PropertyName == p.Name); var valueParser = currentField.GetAttributes <ValueParserAttribute>().SingleOrDefault(); if (valueParser != null) { ParsersMap.Add(new KeyValuePair <string, string>(metadata.PropertyName, valueParser.ParserName)); } } return(new CacheItem { FieldsMap = FieldsMap, ConstsMap = ConstsMap, EnumsMap = EnumsMap, MethodsList = MethodsList, ParsersMap = ParsersMap }); }); FieldsMap = item.FieldsMap; ConstsMap = item.ConstsMap; EnumsMap = item.EnumsMap; MethodsList = item.MethodsList; ParsersMap = item.ParsersMap; }
private Thread[] MakeThreads(string[] keys) { var threads = keys.Select(key => new Thread(load => { var storage = (ConcurrentStack <TestItem>)((object[])load)[0]; var counter = (ConcurrentStack <int>)((object[])load)[1]; var item = ProcessStorage <string, TestItem> .GetOrAdd(key.ToString(), _ => { Debug.WriteLine($"{key} :: {Thread.CurrentThread.ManagedThreadId}"); counter.Push(Thread.CurrentThread.ManagedThreadId); // we want to test that this value factory delegate is invoked only once, even if map is accessed concurrently for the same key Thread.Sleep(500); return(new TestItem { Id = key }); }); storage.Push(item); })).ToArray(); return(threads); }
/// <summary> /// Constructor for expressive model validator. /// </summary> /// <param name="metadata">The model metadata instance.</param> /// <param name="context">The controller context instance.</param> /// <param name="attribute">The expressive attribute instance.</param> /// <exception cref="System.ComponentModel.DataAnnotations.ValidationException"></exception> protected ExpressiveValidator(ModelMetadata metadata, ControllerContext context, T attribute) : base(metadata, context, attribute) { try { Debug.WriteLine($"[ctor entry] process: {Process.GetCurrentProcess().Id}, thread: {Thread.CurrentThread.ManagedThreadId}"); var fieldId = $"{metadata.ContainerType.FullName}.{metadata.PropertyName}".ToLowerInvariant(); AttributeFullId = $"{attribute.TypeId}.{fieldId}".ToLowerInvariant(); AttributeWeakId = $"{typeof(T).FullName}.{fieldId}".ToLowerInvariant(); FieldName = metadata.PropertyName; ResetSuffixAllocation(); var item = ProcessStorage <string, CacheItem> .GetOrAdd(AttributeFullId, _ => // map cache is based on static dictionary, set-up once for entire application instance { // (by design, no reason to recompile once compiled expressions) Debug.WriteLine($"[cache add] process: {Process.GetCurrentProcess().Id}, thread: {Thread.CurrentThread.ManagedThreadId}"); IDictionary <string, Expression> fields = null; attribute.Compile(metadata.ContainerType, parser => { fields = parser.GetFields(); FieldsMap = fields.ToDictionary(x => x.Key, x => Helper.GetCoarseType(x.Value.Type)); ConstsMap = parser.GetConsts(); EnumsMap = parser.GetEnums(); MethodsList = parser.GetMethods(); }); // compile the expression associated with attribute (to be cached for subsequent invocations) AssertClientSideCompatibility(); ParsersMap = fields .Select(kvp => new { FullName = kvp.Key, ParserAttribute = (kvp.Value as MemberExpression)?.Member.GetAttributes <ValueParserAttribute>().SingleOrDefault() }).Where(x => x.ParserAttribute != null) .ToDictionary(x => x.FullName, x => x.ParserAttribute.ParserName); if (!ParsersMap.ContainsKey(metadata.PropertyName)) { var currentField = metadata.ContainerType .GetProperties().Single(p => metadata.PropertyName == p.Name); var valueParser = currentField.GetAttributes <ValueParserAttribute>().SingleOrDefault(); if (valueParser != null) { ParsersMap.Add(new KeyValuePair <string, string>(metadata.PropertyName, valueParser.ParserName)); } } return(new CacheItem { FieldsMap = FieldsMap, ConstsMap = ConstsMap, EnumsMap = EnumsMap, MethodsList = MethodsList, ParsersMap = ParsersMap }); }); FieldsMap = item.FieldsMap; ConstsMap = item.ConstsMap; EnumsMap = item.EnumsMap; MethodsList = item.MethodsList; ParsersMap = item.ParsersMap; Expression = attribute.Expression; IDictionary <string, Guid> errFieldsMap; FormattedErrorMessage = attribute.FormatErrorMessage(metadata.GetDisplayName(), attribute.Expression, metadata.ContainerType, out errFieldsMap); // fields names, in contrast to values, do not change in runtime, so will be provided in message (less code in js) ErrFieldsMap = errFieldsMap; } catch (Exception e) { throw new ValidationException( $"{GetType().Name}: validation applied to {metadata.PropertyName} field failed.", e); } }
public ProcessStorageTest() { ProcessStorage <string, TestItem> .Clear(); }