public ReflectionPropertyViewModel(ClassViewModel effectiveParent, ClassViewModel declaringParent, PropertyInfo propetyInfo) { Parent = declaringParent; EffectiveParent = effectiveParent; Info = propetyInfo; Type = new ReflectionTypeViewModel(Info.PropertyType); }
public SymbolPropertyViewModel(ClassViewModel effectiveParent, ClassViewModel declaringParent, IPropertySymbol symbol) { Parent = declaringParent; EffectiveParent = effectiveParent; Symbol = symbol; Type = new SymbolTypeViewModel(Symbol.Type); }
public static List <ClassViewModel> AddContext(INamedTypeSymbol contextSymbol, string area = "") // where T: AppDbContext { var context = new ClassViewModel(contextSymbol, null, null, false); // Reflect on the AppDbContext return(AddContext(context, area)); }
public static List <ClassViewModel> AddContext(ClassViewModel context, string area = "") { _contextNamespace = context.Namespace; // Lock so that parallel execution only uses this once at a time. lock (_lock) { var models = new List <ClassViewModel>(); foreach (var prop in context.Properties) { if ((prop.Type.IsCollection || prop.IsDbSet) && IsValidViewModelClass(prop.PureType.Name) && !prop.IsInternalUse) { var model = ReflectionRepository.GetClassViewModel(classType: prop.PureType, hasDbSet: prop.IsDbSet); if (model != null) { model.ContextPropertyName = prop.Name; model.OnContext = true; model.ContextPropertyName = prop.Name; models.Add(model); } } } // Check for other associated types that are not dbsets foreach (var model in models.ToList()) { AddChildModels(models, model); } return(models); } }
/// <summary> /// Gets a list of properties that should be searched for text. /// It will first look for any properties that are decorated with the Search attribute. /// If it doesn't find those, it will look for a property called Name or {Class}Name. /// If none of those are found, it will result in returning the property that is the primary key for the object /// </summary> public IEnumerable <SearchableProperty> SearchProperties(ClassViewModel rootModel = null, int depth = 0, int maxDepth = 2) { // Only go down three levels. if (depth == 3) { yield break; } var searchProperties = Properties.Where(f => f.IsSearchable(rootModel)).ToList(); if (searchProperties.Count > 0) { // Process these items to make sure we have things we can search on. foreach (var property in searchProperties) { // Get all the child items foreach (var searchProperty in property.SearchProperties(rootModel, depth, maxDepth)) { yield return(searchProperty); } } yield break; } yield return(new[] { PropertyByName("Name"), Properties.FirstOrDefault(p => p.Name == $"{p.Parent.Name}Name"), PrimaryKey } .Where(p => p != null && p.IsClientProperty && p.HasNotMapped == false) .Select(p => new SearchableValueProperty(p)) .FirstOrDefault()); }
/// <summary> /// Returns true if this property is marked with the Search attribute. /// </summary> public bool IsSearchable(ClassViewModel rootModel) { if (!HasAttribute <SearchAttribute>()) { return(false); } var rootModelName = rootModel?.Name; if (rootModelName == null) { return(true); } var whitelist = this.GetAttributeValue <SearchAttribute>(a => a.RootWhitelist); if (!string.IsNullOrWhiteSpace(whitelist)) { return(whitelist.Split(',').Contains(rootModelName)); } var blacklist = this.GetAttributeValue <SearchAttribute>(a => a.RootBlacklist); if (!string.IsNullOrWhiteSpace(blacklist)) { return(!blacklist.Split(',').Contains(rootModelName)); } return(true); }
/// <summary> /// Returns the fields to search for this object. This could be just the field itself /// or a number of child fields if this is an object or collection. /// </summary> public IEnumerable <SearchableProperty> SearchProperties(ClassViewModel rootModel, int depth = 0, int maxDepth = 2, bool force = false) { if (!force && !IsSearchable(rootModel)) { yield break; } if (this.PureType.HasClassViewModel) { // If we will exceed the depth don't try to query on an object. if (depth < maxDepth) { // Remove this item and add the child's search items with a prepended property name var childProperties = this.Type.PureType.ClassViewModel.SearchProperties(rootModel, depth + 1, maxDepth); if (this.Type.IsCollection) { yield return(new SearchableCollectionProperty(this, childProperties)); } else { yield return(new SearchableObjectProperty(this, childProperties)); } } } else { yield return(new SearchableValueProperty(this)); } }
protected override IReadOnlyCollection <PropertyViewModel> RawProperties(ClassViewModel effectiveParent) => Info .GetProperties() .Select((p, i) => new ReflectionPropertyViewModel(effectiveParent, new ReflectionTypeViewModel(p.DeclaringType).ClassViewModel, p) { ClassFieldOrder = i }) .Cast <PropertyViewModel>() .ToList().AsReadOnly();
private void DiscoverNestedCrudStrategiesOn(ClassViewModel model) { foreach (var nestedType in model.ClientNestedTypes) { AddCrudStrategy(typeof(IDataSource <>), nestedType, _dataSources, model); AddCrudStrategy(typeof(IBehaviors <>), nestedType, _behaviors, model); } }
private void DiscoverExternalPropertyTypesOn(ClassViewModel model) { foreach (var type in model .ClientProperties .Select(p => p.PureType) .Where(t => t.HasClassViewModel)) { ConditionallyAddAndDiscoverExternalPropertyTypesOn(type.ClassViewModel); } }
/// <summary> /// Cache the given model so it can be reused when an instance representing its underlying type is requested. /// </summary> /// <param name="classViewModel">The ClassViewModel to cache.</param> /// <param name="force"> /// True to override any existing object for the underlying type. /// False to preserve any existing object. /// </param> /// <returns>The ClassViewModel that was passed in, for convenience.</returns> private ClassViewModel Cache(ClassViewModel classViewModel, bool force = false) { object key = GetCacheKey(classViewModel); if (force) { _allClassViewModels[key] = classViewModel; } else { _allClassViewModels.GetOrAdd(key, classViewModel); } return(classViewModel); }
private void DiscoverExternalMethodTypesOn(ClassViewModel model) { foreach (var method in model.ClientMethods) { var returnType = method.ResultType.PureType; if (returnType.HasClassViewModel) { // Return type looks like an external type. ConditionallyAddAndDiscoverExternalPropertyTypesOn(returnType.ClassViewModel); } foreach (var arg in method.Parameters.Where(p => !p.IsDI && p.Type.HasClassViewModel)) { // Parameter looks like an external type. ConditionallyAddAndDiscoverExternalPropertyTypesOn(arg.Type.ClassViewModel); } } }
/// <summary> /// Attempt to add the given ClassViewModel as an ExternalType if it isn't already known. /// If its a newly discovered type, recurse into that type's properties as well. /// </summary> /// <param name="externalType"></param> private void ConditionallyAddAndDiscoverExternalPropertyTypesOn(ClassViewModel externalType) { // Don't dig in if: // - This is a known entity type (its not external) // - This is a known custom DTO type (again, not external) // - This is already a known external type (don't infinitely recurse). if ( !Entities.Contains(externalType) && !CustomDtos.Contains(externalType) && !ExternalTypes.Contains(externalType) ) { if (_externalTypes.Add(Cache(externalType))) { DiscoverExternalPropertyTypesOn(externalType); } } }
private bool AddCrudStrategy( Type iface, TypeViewModel strategyType, HashSet <CrudStrategyTypeUsage> set, ClassViewModel declaredFor = null ) { if (!strategyType.IsA(iface)) { return(false); } var servedType = strategyType.GenericArgumentsFor(iface).Single(); if (!servedType.HasClassViewModel) { throw new InvalidOperationException($"{servedType} is not a valid type argument for a {iface}."); } var servedClass = Cache(servedType.ClassViewModel); // See if we were expecting that the strategy be declared for a particular type // by virtue of its nesting. If this type has been overridden to something else by an attribute, then that's wrong. var explicitlyDeclaredFor = strategyType.GetAttributeValue <DeclaredForAttribute>(a => a.DeclaredFor)?.ClassViewModel; if (explicitlyDeclaredFor != null && declaredFor != null && !explicitlyDeclaredFor.Equals(declaredFor)) { throw new InvalidOperationException( $"Expected that {strategyType} is declared for {declaredFor}, but it was explicitly declared for {explicitlyDeclaredFor} instead."); } // Any explicit declaration is OK. Use that, // or the passed in value if no explicit value is given via attribute, // or just the type that is served if neither are present. declaredFor = explicitlyDeclaredFor ?? declaredFor ?? servedClass; if (declaredFor.IsDto && !servedClass.Equals(declaredFor.DtoBaseViewModel)) { throw new InvalidOperationException($"{strategyType} is not a valid {iface} for {declaredFor} - " + $"{strategyType} must satisfy {iface} with type parameter <{declaredFor.DtoBaseViewModel}>."); } set.Add(new CrudStrategyTypeUsage(Cache(strategyType.ClassViewModel), servedClass, declaredFor)); return(true); }
protected override IReadOnlyCollection <PropertyViewModel> RawProperties(ClassViewModel effectiveParent) { var result = Symbol.GetMembers() .Where(s => s.Kind == SymbolKind.Property) .Cast <IPropertySymbol>() .Select((s, i) => new SymbolPropertyViewModel(effectiveParent, this, s) { ClassFieldOrder = i }) .Cast <PropertyViewModel>() .ToList(); // Add properties from the base class if (Symbol.BaseType != null && Symbol.BaseType.Name != "Object") { var parentSymbol = new SymbolClassViewModel(Symbol.BaseType); result.AddRange(parentSymbol.RawProperties(effectiveParent)); } return(result.AsReadOnly()); }
private static void AddChildModels(List <ClassViewModel> models, ClassViewModel model) { foreach (var prop in model.Properties.Where(p => !p.IsInternalUse && p.PureType.IsPOCO && IsValidViewModelClass(p.PureType.Name))) { var propModel = prop.PureType.ClassViewModel; if (propModel != null && !propModel.HasDbSet && !models.Contains(propModel)) { models.Add(propModel); AddChildModels(models, propModel); } } foreach (var method in model.Methods.Where(p => !p.IsInternalUse && !p.ReturnType.IsVoid && p.ReturnType.PureType.IsPOCO)) { // Get a unique key string key = GetKey(method.ReturnType.PureType); lock (models) { if (!models.Any(f => f.Name == method.ReturnType.PureType.Name)) { var methodModel = new ClassViewModel(method.ReturnType.PureType, "", "", false); models.Add(methodModel); AddChildModels(models, methodModel); } } // Iterate each of the incoming arguments and check them foreach (var arg in method.Parameters.Where(p => !p.IsDI && p.Type.IsPOCO)) { string argKey = GetKey(arg.Type); lock (models) { if (!models.Any(f => f.Name == arg.Type.Name)) { var argModel = new ClassViewModel(arg.Type, "", "", false); models.Add(argModel); AddChildModels(models, argModel); } } } } }
internal MethodViewModel(MethodWrapper wrapper, ClassViewModel parent, int classMethodOrder) { Wrapper = wrapper; Parent = parent; ClassMethodOrder = classMethodOrder; }
internal MethodViewModel(ClassViewModel parent) { Parent = parent; }
protected abstract IReadOnlyCollection <PropertyViewModel> RawProperties(ClassViewModel effectiveParent);
private object GetCacheKey(ClassViewModel classViewModel) => (classViewModel.Type as ReflectionTypeViewModel)?.Info as object ?? (classViewModel.Type as SymbolTypeViewModel)?.Symbol as object ?? throw new NotSupportedException("Unknown subtype of TypeViewModel");
/// <summary> /// Adds a context to the reflection repository. Do this on startup with all the contexts. /// </summary> /// <typeparam name="t">Type of DbContext to add.</typeparam> /// <returns></returns> public static List <ClassViewModel> AddContext(Type t, string area = "") { var context = new ClassViewModel(t, null, null, false); return(AddContext(context, area)); }
public SymbolMethodViewModel(IMethodSymbol symbol, ClassViewModel parent) : base(parent) { Symbol = symbol; }
public ReflectionMethodViewModel(ClassViewModel parent, MethodInfo methodInfo) : base(parent) { Info = methodInfo; }