123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Threading.Tasks;
- namespace InABox.Core
- {
- public class AutoDataModel<T> : DataModel<T> where T : Entity, IPersistent, IRemotable, new()
- {
- private static Type[]? _allo2mtypes;
- // Method; Parent Column; Child Column; Columns expression; Table Name
- private static readonly List<Tuple<MethodInfo, Expression, Expression, IColumns, string>> children =
- new List<Tuple<MethodInfo, Expression, Expression, IColumns, string>>();
- // Method; Parent Column; Child Column; Table Name
- private static readonly List<Tuple<MethodInfo, Expression, Expression, string>> lookups =
- new List<Tuple<MethodInfo, Expression, Expression, string>>();
- //
- private static readonly List<Tuple<MethodInfo, Expression, Expression, IColumns, string>> manyToManys0 =
- new List<Tuple<MethodInfo, Expression, Expression, IColumns, string>>();
- private static readonly List<Tuple<MethodInfo, Expression, Expression, string, string>> manyToManys1 =
- new List<Tuple<MethodInfo, Expression, Expression, string, string>>();
- //private List<Tuple<String,Type>> _lookuptables = new List<Tuple<String,Type>>();
- private readonly List<Tuple<Type, string, bool>> _childtables = new List<Tuple<Type, string, bool>>();
- public AutoDataModel(Filter<T> filter, Columns<T>? columns, SortOrder<T>? sort) : base(filter, columns, sort)
- {
- //var props = CoreUtils.PropertyList(typeof(T), x => x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink)));
- //foreach (var prop in props)
- //{
- // var lookuptype = prop.PropertyType.GetInheritedGenericTypeArguments().FirstOrDefault();
- // if (lookuptype != null)
- // {
- // MethodInfo method = this.GetType().GetMethod("AddLookupTable").MakeGenericMethod(typeof(T), lookuptype);
- // var source = CoreUtils.GetPropertyExpression(typeof(T), prop.Name + ".ID", typeof(object));
- // var target = CoreUtils.GetPropertyExpression(lookuptype, "ID", typeof(object));
- // method.Invoke(this, new object[] { source, target, false, null, prop.Name });
- // _lookuptables.Add(new Tuple<String,Type>(prop.Name,lookuptype));
- // }
- //}
- var headName = TableName<T>();
- if (_allo2mtypes == null)
- {
- _allo2mtypes = CoreUtils.TypeList(
- AppDomain.CurrentDomain.GetAssemblies(),
- x => x.GetInterfaces().Any(
- i => i.IsGenericType
- && (i.GetGenericTypeDefinition() == typeof(IOneToMany<>)
- || i.GetGenericTypeDefinition() == typeof(IManyToMany<,>)))
- ).ToArray();
- IEnumerable<Type> maps = _allo2mtypes.Where(
- x => x.GetInterfaces().Any(
- i => i.IsGenericType
- && i.GetGenericTypeDefinition() == typeof(IOneToMany<>)
- && i.GenericTypeArguments.Contains(typeof(T)))
- && !typeof(ISkipLoad).IsAssignableFrom(x)).OrderBy(x => x.EntityName());
- var childMethod = GetType().GetMethods().Where(x => string.Equals(x.Name, "AddChildTable") && x.IsGenericMethod).FirstOrDefault();
- var lookupMethod = GetType().GetMethods().Where(x => string.Equals(x.Name, "AddLookupTable") && x.IsGenericMethod).FirstOrDefault();
- foreach (var map in maps)
- {
- var method = childMethod.MakeGenericMethod(typeof(T), map);
- var source = CoreUtils.GetPropertyExpression(typeof(T), "ID", typeof(object));
- var prop = map.GetProperties().FirstOrDefault(
- x => x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink)) &&
- !x.CustomAttributes.Any(y => y.AttributeType == typeof(ObsoleteAttribute)) &&
- x.PropertyType.GetInheritedGenericTypeArguments().FirstOrDefault() == typeof(T));
- var target = CoreUtils.GetPropertyExpression(map, prop.Name + ".ID", typeof(object));
- var cols = Core.Columns.Create(map);
- var columnList = CoreUtils.GetColumnNames(map,
- x => !x.DeclaringType.IsAssignableFrom(map) || x.Name.Split('.', StringSplitOptions.None).First() != prop.Name);
- foreach (var col in columnList) cols.Add(col);
- cols.Add(prop.Name + ".ID");
- children.Add(new Tuple<MethodInfo, Expression, Expression, IColumns, string>(method, source, target, cols,
- headName + "_" + TableName(map)));
- //method.Invoke(this, new object[] { source, target, null, columns, false, null, headName + "_" + TableName(map) });
- //_childtables.Add(new Tuple<Type, String, bool>(map, prop.Name, false));
- }
- var properties = typeof(T).GetProperties().Where(
- x => x.PropertyType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityLink<>))
- && !x.CustomAttributes.Any(y => y.AttributeType == typeof(ObsoleteAttribute)));
- foreach (var property in properties)
- {
- var propType = property.PropertyType;
- var otherType = propType.GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEntityLink<>))
- .FirstOrDefault().GenericTypeArguments[0];
- if (!typeof(ISkipLoad).IsAssignableFrom(otherType))
- {
- var method = lookupMethod.MakeGenericMethod(typeof(T), otherType);
- var source = CoreUtils.GetPropertyExpression(typeof(T), property.Name + ".ID", typeof(object));
- var target = CoreUtils.GetPropertyExpression(otherType, "ID", typeof(object));
- var tableNameAttribute = property.GetCustomAttribute<DataModelTableNameAttribute>();
- var tableName = tableNameAttribute?.TableName ?? TableName(otherType);
- lookups.Add(new Tuple<MethodInfo, Expression, Expression, string>(method, source, target,
- headName + "_" + tableName));
- //method.Invoke(this, new object[] { source, target, null, null, false, null, headName + "_" + TableName(otherType) });
- //_childtables.Add(new Tuple<Type, String, bool>(otherType, property.Name, true));
- }
- }
- IEnumerable<Type> mapsLookup = _allo2mtypes.Where(
- x => x.GetInterfaces().Any(
- i => i.IsGenericType
- && i.GetGenericTypeDefinition() == typeof(IManyToMany<,>)
- && i.GenericTypeArguments.Contains(typeof(T)))).OrderBy(x => x.EntityName());
- foreach (var map in mapsLookup)
- {
- var method = childMethod.MakeGenericMethod(typeof(T), map);
- var source = CoreUtils.GetPropertyExpression(typeof(T), "ID", typeof(object));
- var prop = map.GetProperties().FirstOrDefault(
- x => x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink))
- && !x.CustomAttributes.Any(y => y.AttributeType == typeof(ObsoleteAttribute))
- && x.PropertyType.GetInheritedGenericTypeArguments().FirstOrDefault() == typeof(T));
- var target = CoreUtils.GetPropertyExpression(map, prop.Name + ".ID", typeof(object));
- var lookupAlias = headName + "_" + TableName(map);
- var cols = Core.Columns.Create(map);
- var columnList = CoreUtils.GetColumnNames(map, x => !x.DeclaringType.IsAssignableFrom(map) || x.Name != prop.Name);
- foreach (var col in columnList) cols.Add(col);
- cols.Add(prop.Name + ".ID");
- manyToManys0.Add(new Tuple<MethodInfo, Expression, Expression, IColumns, string>(method, source, target, cols, lookupAlias));
- //method.Invoke(this, new object[] { source, target, null, columns, false, null, lookupAlias });
- //_childtables.Add(new Tuple<Type, String, bool>(map, prop.Name, false));
- var otherType = map.GetInterfaces().Where(
- x => x.IsGenericType
- && x.GetGenericTypeDefinition() == typeof(IManyToMany<,>))
- .FirstOrDefault().GenericTypeArguments.Where(x => x != typeof(T)).FirstOrDefault();
- if (!typeof(ISkipLoad).IsAssignableFrom(otherType))
- {
- method = lookupMethod.MakeGenericMethod(map, otherType);
- prop = map.GetProperties().FirstOrDefault(
- x => x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink))
- && !x.CustomAttributes.Any(y => y.AttributeType == typeof(ObsoleteAttribute))
- && x.PropertyType.GetInheritedGenericTypeArguments().FirstOrDefault() == otherType);
- source = CoreUtils.GetPropertyExpression(map, prop.Name + ".ID", typeof(object));
- target = CoreUtils.GetPropertyExpression(otherType, "ID", typeof(object));
- manyToManys1.Add(new Tuple<MethodInfo, Expression, Expression, string, string>(method, source, target, lookupAlias,
- lookupAlias + "_" + TableName(otherType)));
- //method.Invoke(this, new object[] { source, target, null, null, false, lookupAlias, lookupAlias + "_" + TableName(otherType) });
- //_childtables.Add(new Tuple<Type, String, bool>(map, prop.Name, false));
- }
- }
- }
- foreach (var child in children)
- child.Item1.Invoke(this, new object?[] { child.Item2, child.Item3, null, child.Item4, false, null, child.Item5 });
- foreach (var lookup in lookups)
- lookup.Item1.Invoke(this, new object?[] { lookup.Item2, lookup.Item3, null, null, false, null, lookup.Item4 });
- foreach (var manyToMany0 in manyToManys0)
- manyToMany0.Item1.Invoke(this,
- new object?[] { manyToMany0.Item2, manyToMany0.Item3, null, manyToMany0.Item4, false, null, manyToMany0.Item5 });
- foreach (var manyToMany1 in manyToManys1)
- manyToMany1.Item1.Invoke(this,
- new object?[] { manyToMany1.Item2, manyToMany1.Item3, null, null, false, manyToMany1.Item4, manyToMany1.Item5 });
- }
- public AutoDataModel(Filter<T> filter): this(filter, null, null) { }
- public override string Name => typeof(T).EntityName().Split('.').Last();
- }
- }
|