/// <summary> /// Gets a list of <see cref="OdinAttributeProcessor"/> to process attributes for the specified property. /// </summary> /// <param name="property">The property to find attribute porcessors for.</param> /// <returns>List of <see cref="OdinAttributeProcessor"/> to process attributes for the speicied member.</returns> public override List <OdinAttributeProcessor> GetSelfProcessors(InspectorProperty property) { List <OdinAttributeProcessor> processors = new List <OdinAttributeProcessor>(); CachedMatchesList.Clear(); CachedMatchesList.Add(SearchIndex.GetMatches(Type.EmptyTypes)); if (property.ValueEntry != null) { CachedMatchesList.Add(SearchIndex.GetMatches(property.ValueEntry.TypeOfValue)); } var results = TypeSearchIndex.GetCachedMergedQueryResults(CachedMatchesList); for (int i = 0; i < results.Length; i++) { var result = results[i]; var resolver = GetResolverInstance(result.MatchedType); if (resolver.CanProcessSelfAttributes(property)) { processors.Add(resolver); } } return(processors); }
public static void GetDefaultPropertyDrawers(InspectorProperty property, List <TypeSearchResult> resultList) { resultList.Clear(); var queries = CachedQueryResultList; queries.Clear(); // First we make and gather lots of small queries, which are essentially instant, as they are // all cached by the search index. { // Empty query (for all drawers with no type constraints at all) queries.Add(SearchIndex.GetMatches(Type.EmptyTypes)); // Value query if (property.ValueEntry != null) { queries.Add(SearchIndex.GetMatches(property.ValueEntry.TypeOfValue)); } // Attribute queries for (int i = 0; i < property.Attributes.Count; i++) { var attr = property.Attributes[i].GetType(); queries.Add(SearchIndex.GetMatches(attr)); // Attribute and value query if (property.ValueEntry != null) { queries.Add(SearchIndex.GetMatches(attr, property.ValueEntry.TypeOfValue)); if (InvalidAttributeTargetUtility.ShowInvalidAttributeErrorFor(property, attr)) { queries.Add(GetInvalidAttributeTypeSearchResult(attr)); } } } } var finalResults = TypeSearchIndex.GetCachedMergedQueryResults(queries); // Build up the final result list, filtering invalid drawer types away // as we go. for (int i = 0; i < finalResults.Length; i++) { var result = finalResults[i]; if (DrawerTypeCanDrawProperty(result.MatchedType, property)) { resultList.Add(finalResults[i]); } } }
protected virtual Validator[] CreateValidators(Type valueType) { List <Validator> validators = new List <Validator>(); SearchResultList.Clear(); SearchResultList.Add(ValueValidatorSearchIndex.GetMatches(Type.EmptyTypes)); SearchResultList.Add(ValueValidatorSearchIndex.GetMatches(valueType)); // @TODO Tor support this so it also works with attributes despite there being no member //var attributes = valueType.GetAttributes<Attribute>().ToList(); //foreach (var attribute in attributes) //{ // SearchResultList.Add(AttributeValidatorSearchIndex.GetMatches(attribute.GetType())); // SearchResultList.Add(AttributeValidatorSearchIndex.GetMatches(attribute.GetType(), valueType)); //} ResultList.Clear(); TypeSearchIndex.MergeQueryResultsIntoList(SearchResultList, ResultList); for (int i = 0; i < ResultList.Count; i++) { var result = ResultList[i]; if (this.CustomValidatorFilter != null && !this.CustomValidatorFilter(result.MatchedType)) { continue; } try { var validator = (Validator)Activator.CreateInstance(result.MatchedType); if (validator.CanValidateValues() && validator.CanValidateValue(valueType)) { validator.Initialize(valueType); validators.Add(validator); } } catch (Exception ex) { validators.Add(new BrokenAttributeValidator(result.MatchedType, ValidationKind.Value, "Creating instance of validator '" + result.MatchedType.GetNiceName() + "' failed with exception: " + ex.ToString())); } } return(validators.ToArray()); }
/// <summary> /// Gets an <see cref="OdinPropertyResolver"/> instance for the specified property. /// </summary> /// <param name="property">The property to get an <see cref="OdinPropertyResolver"/> instance for.</param> /// <returns>An instance of <see cref="OdinPropertyResolver"/> to resolver the specified property.</returns> public override OdinPropertyResolver GetResolver(InspectorProperty property) { if (property.Tree.IsStatic && property == property.Tree.SecretRootProperty) { return(OdinPropertyResolver.Create(typeof(StaticRootPropertyResolver <>).MakeGenericType(property.ValueEntry.TypeOfValue), property)); } var queries = QueryResultsList; queries.Clear(); queries.Add(SearchIndex.GetMatches(Type.EmptyTypes)); Type typeOfValue = property.ValueEntry != null ? property.ValueEntry.TypeOfValue : null; if (typeOfValue != null) { queries.Add(SearchIndex.GetMatches(typeOfValue)); for (int i = 0; i < property.Attributes.Count; i++) { queries.Add(SearchIndex.GetMatches(typeOfValue, property.Attributes[i].GetType())); } } TypeSearchIndex.MergeQueryResultsIntoList(queries, MergedSearchResultsList); for (int i = 0; i < MergedSearchResultsList.Count; i++) { var info = MergedSearchResultsList[i]; if (GetEmptyResolverInstance(info.MatchedType).CanResolveForPropertyFilter(property)) { return(OdinPropertyResolver.Create(info.MatchedType, property)); } } return(OdinPropertyResolver.Create <EmptyPropertyResolver>(property)); }
public static List <OdinPropertyProcessor> GetMemberProcessors(InspectorProperty property) { var queries = CachedQueryList; queries.Clear(); //var results = CachedResultList; //results.Clear(); queries.Add(SearchIndex.GetMatches(Type.EmptyTypes)); if (property.ValueEntry != null) { var valueType = property.ValueEntry.TypeOfValue; queries.Add(SearchIndex.GetMatches(valueType)); for (int i = 0; i < property.Attributes.Count; i++) { queries.Add(SearchIndex.GetMatches(valueType, property.Attributes[i].GetType())); } } var results = TypeSearchIndex.GetCachedMergedQueryResults(queries); List <OdinPropertyProcessor> processors = new List <OdinPropertyProcessor>(); for (int i = 0; i < results.Length; i++) { var result = results[i]; if (GetEmptyInstance(result.MatchedType).CanProcessForProperty(property)) { processors.Add(OdinPropertyProcessor.Create(result.MatchedType, property)); } } return(processors); }
public static IEnumerable <TypeSearchResult> GetDefaultPropertyDrawers(InspectorProperty property) { var queries = CachedQueryResultList; queries.Clear(); // First we make and gather lots of small queries, which are essentially instant, as they are // all cached by the search index. { // Empty query (for all drawers with no type constraints at all) queries.Add(SearchIndex.GetMatches(Type.EmptyTypes)); // Value query if (property.ValueEntry != null) { queries.Add(SearchIndex.GetMatches(property.ValueEntry.TypeOfValue)); } // Attribute queries for (int i = 0; i < property.Attributes.Count; i++) { var attr = property.Attributes[i].GetType(); queries.Add(SearchIndex.GetMatches(attr)); // Attribute and value query if (property.ValueEntry != null) { queries.Add(SearchIndex.GetMatches(attr, property.ValueEntry.TypeOfValue)); if (InvalidAttributeTargetUtility.ShowInvalidAttributeErrorFor(property, attr)) { queries.Add(new TypeSearchResult[] { new TypeSearchResult() { MatchedInfo = new TypeSearchInfo() { MatchType = typeof(InvalidAttributeNotificationDrawer <>), Priority = double.MaxValue, Targets = Type.EmptyTypes }, MatchedRule = InvalidAttributeRule, MatchedTargets = Type.EmptyTypes, MatchedType = typeof(InvalidAttributeNotificationDrawer <>).MakeGenericType(attr) } }); } } } } var finalResults = TypeSearchIndex.GetCachedMergedQueryResults(queries); // Yield the final result array, filtering invalid drawer types away // as we go. for (int i = 0; i < finalResults.Length; i++) { var result = finalResults[i]; if (DrawerTypeCanDrawProperty(result.MatchedType, property)) { yield return(finalResults[i]); } } }
static DefaultValidatorLocator() { ValueValidatorSearchIndex = new TypeSearchIndex(); AttributeValidatorSearchIndex = new TypeSearchIndex(); foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var attr in assembly.GetAttributes <RegisterValidatorAttribute>()) { var type = attr.ValidatorType; if (!type.InheritsFrom <Validator>()) { Debug.LogError("The registered validator type " + attr.ValidatorType.GetNiceFullName() + " is not derived from " + typeof(Validator).GetNiceFullName()); continue; } if (type.ImplementsOpenGenericClass(typeof(AttributeValidator <,>))) { AttributeValidatorSearchIndex.AddIndexedType(new TypeSearchInfo() { MatchType = type, Targets = type.GetArgumentsOfInheritedOpenGenericClass(typeof(AttributeValidator <,>)), Priority = attr.Priority }); } else if (type.ImplementsOpenGenericClass(typeof(AttributeValidator <>))) { AttributeValidatorSearchIndex.AddIndexedType(new TypeSearchInfo() { MatchType = type, Targets = type.GetArgumentsOfInheritedOpenGenericClass(typeof(AttributeValidator <>)), Priority = attr.Priority }); } else if (type.ImplementsOpenGenericClass(typeof(ValueValidator <>))) { ValueValidatorSearchIndex.AddIndexedType(new TypeSearchInfo() { MatchType = type, Targets = type.GetArgumentsOfInheritedOpenGenericClass(typeof(ValueValidator <>)), Priority = attr.Priority }); } else { ValueValidatorSearchIndex.AddIndexedType(new TypeSearchInfo() { MatchType = type, Targets = Type.EmptyTypes, Priority = attr.Priority, }); AttributeValidatorSearchIndex.AddIndexedType(new TypeSearchInfo() { MatchType = type, Targets = Type.EmptyTypes, Priority = attr.Priority, }); } } } }
protected virtual Validator[] CreateValidators(MemberInfo member, Type memberValueType, bool isCollectionElement) { List <Validator> validators = new List <Validator>(); SearchResultList.Clear(); SearchResultList.Add(AttributeValidatorSearchIndex.GetMatches(Type.EmptyTypes)); SearchResultList.Add(ValueValidatorSearchIndex.GetMatches(memberValueType)); var attributes = member.GetAttributes <Attribute>().ToList(); attributes.AddRange(memberValueType.GetAttributes <Attribute>()); foreach (var attribute in attributes) { if (isCollectionElement && attribute.GetType().IsDefined <DontApplyToListElementsAttribute>(true)) { continue; } SearchResultList.Add(AttributeValidatorSearchIndex.GetMatches(attribute.GetType())); SearchResultList.Add(AttributeValidatorSearchIndex.GetMatches(attribute.GetType(), memberValueType)); } ResultList.Clear(); AttributeNumberMap.Clear(); TypeSearchIndex.MergeQueryResultsIntoList(SearchResultList, ResultList); for (int i = 0; i < ResultList.Count; i++) { var result = ResultList[i]; if (this.CustomValidatorFilter != null && !this.CustomValidatorFilter(result.MatchedType)) { continue; } try { Validator validator = (Validator)Activator.CreateInstance(result.MatchedType); if (validator is IAttributeValidator) { Attribute validatorAttribute = null; Type attrType = result.MatchedTargets[0]; if (!attrType.InheritsFrom <Attribute>()) { throw new NotSupportedException("Please don't manually implement the IAttributeValidator interface on any types; it's a special snowflake."); } int number, seen = 0; AttributeNumberMap.TryGetValue(attrType, out number); for (int j = 0; j < attributes.Count; j++) { var attr = attributes[j]; if (attr.GetType() == attrType) { if (seen == number) { validatorAttribute = attr; break; } else { seen++; } } } if (validatorAttribute == null) { throw new Exception("Could not find the correctly numbered attribute of type '" + attrType.GetNiceFullName() + "' on member " + member.DeclaringType.GetNiceName() + "." + member.Name + "; found " + seen + " attributes of that type, but needed number " + number + "."); } (validator as IAttributeValidator).SetAttributeInstance(validatorAttribute); number++; AttributeNumberMap[attrType] = number; } if (validator.CanValidateValues() && validator.CanValidateValue(memberValueType)) { validator.Initialize(memberValueType); validators.Add(validator); } else if (validator.CanValidateMembers() && validator.CanValidateMember(member, memberValueType)) { validator.Initialize(member, memberValueType); validators.Add(validator); } } catch (Exception ex) { validators.Add(new BrokenAttributeValidator(result.MatchedType, ValidationKind.Member, "Creating instance of validator '" + result.MatchedType.GetNiceName() + "' failed with exception: " + ex.ToString())); } } return(validators.ToArray()); }