mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-20 04:48:16 +08:00
arrange
This commit is contained in:
@ -34,16 +34,20 @@ namespace FreeSql.Internal {
|
||||
|
||||
ConcurrentDictionary<Type, TableAttribute> dicConfigEntity = new ConcurrentDictionary<Type, TableAttribute>();
|
||||
internal ICodeFirst ConfigEntity<T>(Action<TableFluent<T>> entity) {
|
||||
if (entity == null) return _orm.CodeFirst;
|
||||
var type = typeof(T);
|
||||
var table = dicConfigEntity.GetOrAdd(type, new TableAttribute());
|
||||
var fluent = new TableFluent<T>(table);
|
||||
entity?.Invoke(fluent);
|
||||
entity.Invoke(fluent);
|
||||
Utils.GetTableByEntity(type, this, true); //update cache
|
||||
return _orm.CodeFirst;
|
||||
}
|
||||
internal ICodeFirst ConfigEntity(Type type, Action<TableFluent> entity) {
|
||||
if (entity == null) return _orm.CodeFirst;
|
||||
var table = dicConfigEntity.GetOrAdd(type, new TableAttribute());
|
||||
var fluent = new TableFluent(type, table);
|
||||
entity?.Invoke(fluent);
|
||||
entity.Invoke(fluent);
|
||||
Utils.GetTableByEntity(type, this, true); //update cache
|
||||
return _orm.CodeFirst;
|
||||
}
|
||||
internal TableAttribute GetEntityTableAttribute(Type type) {
|
||||
|
@ -24,10 +24,10 @@ namespace FreeSql.Internal {
|
||||
class Utils {
|
||||
|
||||
static ConcurrentDictionary<string, ConcurrentDictionary<Type, TableInfo>> _cacheGetTableByEntity = new ConcurrentDictionary<string, ConcurrentDictionary<Type, TableInfo>>();
|
||||
internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
|
||||
internal static TableInfo GetTableByEntity(Type entity, CommonUtils common, bool isReCache = false) {
|
||||
if (entity.FullName.StartsWith("<>f__AnonymousType")) return null;
|
||||
var tbc = _cacheGetTableByEntity.GetOrAdd(common.DbName, k1 => new ConcurrentDictionary<Type, TableInfo>()); //区分数据库类型缓存
|
||||
if (tbc.TryGetValue(entity, out var trytb)) return trytb;
|
||||
if (isReCache == false && tbc.TryGetValue(entity, out var trytb)) return trytb;
|
||||
if (common.CodeFirst.GetDbInfo(entity) != null) return null;
|
||||
|
||||
var tbattr = common.GetEntityTableAttribute(entity);
|
||||
@ -105,7 +105,7 @@ namespace FreeSql.Internal {
|
||||
foreach (var col in trytb.Primarys)
|
||||
col.Attribute.IsPrimary = true;
|
||||
}
|
||||
tbc.TryAdd(entity, trytb);
|
||||
tbc.AddOrUpdate(entity, trytb, (oldkey, oldval) => trytb);
|
||||
|
||||
#region virtual 属性延时加载,动态产生新的重写类
|
||||
if (common.CodeFirst.IsLazyLoading && propsLazy.Any()) {
|
||||
|
@ -1,280 +1,280 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using FreeSql.Internal.Model;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Npgsql.LegacyPostgis;
|
||||
using NpgsqlTypes;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
//using FreeSql.DataAnnotations;
|
||||
//using FreeSql.Internal.Model;
|
||||
//using Newtonsoft.Json.Linq;
|
||||
//using Npgsql.LegacyPostgis;
|
||||
//using NpgsqlTypes;
|
||||
//using System;
|
||||
//using System.Collections;
|
||||
//using System.Collections.Concurrent;
|
||||
//using System.Collections.Generic;
|
||||
//using System.Diagnostics;
|
||||
//using System.Linq;
|
||||
//using System.Net;
|
||||
//using System.Net.NetworkInformation;
|
||||
//using System.Reflection;
|
||||
//using System.Text.RegularExpressions;
|
||||
//using System.Threading;
|
||||
|
||||
namespace FreeSql.Internal {
|
||||
class UtilsReflection {
|
||||
//namespace FreeSql.Internal {
|
||||
// class UtilsReflection {
|
||||
|
||||
static ConcurrentDictionary<string, TableInfo> _cacheGetTableByEntity = new ConcurrentDictionary<string, TableInfo>();
|
||||
internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
|
||||
if (entity.FullName.StartsWith("<>f__AnonymousType")) return null;
|
||||
if (_cacheGetTableByEntity.TryGetValue($"{common.DbName}-{entity.FullName}", out var trytb)) return trytb; //区分数据库类型缓存
|
||||
if (common.CodeFirst.GetDbInfo(entity) != null) return null;
|
||||
// static ConcurrentDictionary<string, TableInfo> _cacheGetTableByEntity = new ConcurrentDictionary<string, TableInfo>();
|
||||
// internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
|
||||
// if (entity.FullName.StartsWith("<>f__AnonymousType")) return null;
|
||||
// if (_cacheGetTableByEntity.TryGetValue($"{common.DbName}-{entity.FullName}", out var trytb)) return trytb; //区分数据库类型缓存
|
||||
// if (common.CodeFirst.GetDbInfo(entity) != null) return null;
|
||||
|
||||
var tbattr = entity.GetCustomAttributes(typeof(TableAttribute), false).LastOrDefault() as TableAttribute;
|
||||
trytb = new TableInfo();
|
||||
trytb.Type = entity;
|
||||
trytb.Properties = entity.GetProperties().ToDictionary(a => a.Name, a => a, StringComparer.CurrentCultureIgnoreCase);
|
||||
trytb.CsName = entity.Name;
|
||||
trytb.DbName = (tbattr?.Name ?? entity.Name);
|
||||
trytb.DbOldName = tbattr?.OldName;
|
||||
if (common.CodeFirst.IsSyncStructureToLower) {
|
||||
trytb.DbName = trytb.DbName.ToLower();
|
||||
trytb.DbOldName = trytb.DbOldName?.ToLower();
|
||||
}
|
||||
trytb.SelectFilter = tbattr?.SelectFilter;
|
||||
foreach (var p in trytb.Properties.Values) {
|
||||
var tp = common.CodeFirst.GetDbInfo(p.PropertyType);
|
||||
//if (tp == null) continue;
|
||||
var colattr = p.GetCustomAttributes(typeof(ColumnAttribute), false).LastOrDefault() as ColumnAttribute;
|
||||
if (tp == null && colattr == null) continue;
|
||||
if (colattr == null)
|
||||
colattr = new ColumnAttribute {
|
||||
Name = p.Name,
|
||||
DbType = tp.Value.dbtypeFull,
|
||||
IsIdentity = false,
|
||||
IsNullable = tp.Value.isnullable ?? true,
|
||||
IsPrimary = false,
|
||||
};
|
||||
if (string.IsNullOrEmpty(colattr.DbType)) colattr.DbType = tp?.dbtypeFull ?? "varchar(255)";
|
||||
colattr.DbType = colattr.DbType.ToUpper();
|
||||
// var tbattr = entity.GetCustomAttributes(typeof(TableAttribute), false).LastOrDefault() as TableAttribute;
|
||||
// trytb = new TableInfo();
|
||||
// trytb.Type = entity;
|
||||
// trytb.Properties = entity.GetProperties().ToDictionary(a => a.Name, a => a, StringComparer.CurrentCultureIgnoreCase);
|
||||
// trytb.CsName = entity.Name;
|
||||
// trytb.DbName = (tbattr?.Name ?? entity.Name);
|
||||
// trytb.DbOldName = tbattr?.OldName;
|
||||
// if (common.CodeFirst.IsSyncStructureToLower) {
|
||||
// trytb.DbName = trytb.DbName.ToLower();
|
||||
// trytb.DbOldName = trytb.DbOldName?.ToLower();
|
||||
// }
|
||||
// trytb.SelectFilter = tbattr?.SelectFilter;
|
||||
// foreach (var p in trytb.Properties.Values) {
|
||||
// var tp = common.CodeFirst.GetDbInfo(p.PropertyType);
|
||||
// //if (tp == null) continue;
|
||||
// var colattr = p.GetCustomAttributes(typeof(ColumnAttribute), false).LastOrDefault() as ColumnAttribute;
|
||||
// if (tp == null && colattr == null) continue;
|
||||
// if (colattr == null)
|
||||
// colattr = new ColumnAttribute {
|
||||
// Name = p.Name,
|
||||
// DbType = tp.Value.dbtypeFull,
|
||||
// IsIdentity = false,
|
||||
// IsNullable = tp.Value.isnullable ?? true,
|
||||
// IsPrimary = false,
|
||||
// };
|
||||
// if (string.IsNullOrEmpty(colattr.DbType)) colattr.DbType = tp?.dbtypeFull ?? "varchar(255)";
|
||||
// colattr.DbType = colattr.DbType.ToUpper();
|
||||
|
||||
if (tp != null && tp.Value.isnullable == null) colattr.IsNullable = tp.Value.dbtypeFull.Contains("NOT NULL") == false;
|
||||
if (colattr.DbType?.Contains("NOT NULL") == true) colattr.IsNullable = false;
|
||||
if (string.IsNullOrEmpty(colattr.Name)) colattr.Name = p.Name;
|
||||
if (common.CodeFirst.IsSyncStructureToLower) colattr.Name = colattr.Name.ToLower();
|
||||
// if (tp != null && tp.Value.isnullable == null) colattr.IsNullable = tp.Value.dbtypeFull.Contains("NOT NULL") == false;
|
||||
// if (colattr.DbType?.Contains("NOT NULL") == true) colattr.IsNullable = false;
|
||||
// if (string.IsNullOrEmpty(colattr.Name)) colattr.Name = p.Name;
|
||||
// if (common.CodeFirst.IsSyncStructureToLower) colattr.Name = colattr.Name.ToLower();
|
||||
|
||||
if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false) {
|
||||
colattr.IsNullable = false;
|
||||
colattr.DbType += " NOT NULL";
|
||||
}
|
||||
if (colattr.IsNullable == true && colattr.DbType.Contains("NOT NULL")) colattr.DbType = colattr.DbType.Replace("NOT NULL", "");
|
||||
colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m => {
|
||||
var tmpLt = Regex.Replace(m.Groups[0].Value, @"\s", "");
|
||||
if (tmpLt.Contains("CHAR")) tmpLt = tmpLt.Replace("CHAR", " CHAR");
|
||||
if (tmpLt.Contains("BYTE")) tmpLt = tmpLt.Replace("BYTE", " BYTE");
|
||||
return tmpLt;
|
||||
});
|
||||
colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(Activator.CreateInstance(trytb.Type));
|
||||
if (colattr.DbDefautValue == null) colattr.DbDefautValue = tp?.defaultValue;
|
||||
if (colattr.IsNullable == false && colattr.DbDefautValue == null)
|
||||
colattr.DbDefautValue = Activator.CreateInstance(p.PropertyType.IsNullableType() ? p.PropertyType.GenericTypeArguments.FirstOrDefault() : p.PropertyType);
|
||||
// if ((colattr.IsNullable != true || colattr.IsIdentity == true || colattr.IsPrimary == true) && colattr.DbType.Contains("NOT NULL") == false) {
|
||||
// colattr.IsNullable = false;
|
||||
// colattr.DbType += " NOT NULL";
|
||||
// }
|
||||
// if (colattr.IsNullable == true && colattr.DbType.Contains("NOT NULL")) colattr.DbType = colattr.DbType.Replace("NOT NULL", "");
|
||||
// colattr.DbType = Regex.Replace(colattr.DbType, @"\([^\)]+\)", m => {
|
||||
// var tmpLt = Regex.Replace(m.Groups[0].Value, @"\s", "");
|
||||
// if (tmpLt.Contains("CHAR")) tmpLt = tmpLt.Replace("CHAR", " CHAR");
|
||||
// if (tmpLt.Contains("BYTE")) tmpLt = tmpLt.Replace("BYTE", " BYTE");
|
||||
// return tmpLt;
|
||||
// });
|
||||
// colattr.DbDefautValue = trytb.Properties[p.Name].GetValue(Activator.CreateInstance(trytb.Type));
|
||||
// if (colattr.DbDefautValue == null) colattr.DbDefautValue = tp?.defaultValue;
|
||||
// if (colattr.IsNullable == false && colattr.DbDefautValue == null)
|
||||
// colattr.DbDefautValue = Activator.CreateInstance(p.PropertyType.IsNullableType() ? p.PropertyType.GenericTypeArguments.FirstOrDefault() : p.PropertyType);
|
||||
|
||||
var col = new ColumnInfo {
|
||||
Table = trytb,
|
||||
CsName = p.Name,
|
||||
CsType = p.PropertyType,
|
||||
Attribute = colattr
|
||||
};
|
||||
trytb.Columns.Add(colattr.Name, col);
|
||||
trytb.ColumnsByCs.Add(p.Name, col);
|
||||
}
|
||||
trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
|
||||
if (trytb.Primarys.Any() == false) {
|
||||
trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity == true).ToArray();
|
||||
foreach(var col in trytb.Primarys)
|
||||
col.Attribute.IsPrimary = true;
|
||||
}
|
||||
_cacheGetTableByEntity.TryAdd(entity.FullName, trytb);
|
||||
return trytb;
|
||||
}
|
||||
// var col = new ColumnInfo {
|
||||
// Table = trytb,
|
||||
// CsName = p.Name,
|
||||
// CsType = p.PropertyType,
|
||||
// Attribute = colattr
|
||||
// };
|
||||
// trytb.Columns.Add(colattr.Name, col);
|
||||
// trytb.ColumnsByCs.Add(p.Name, col);
|
||||
// }
|
||||
// trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsPrimary == true).ToArray();
|
||||
// if (trytb.Primarys.Any() == false) {
|
||||
// trytb.Primarys = trytb.Columns.Values.Where(a => a.Attribute.IsIdentity == true).ToArray();
|
||||
// foreach(var col in trytb.Primarys)
|
||||
// col.Attribute.IsPrimary = true;
|
||||
// }
|
||||
// _cacheGetTableByEntity.TryAdd(entity.FullName, trytb);
|
||||
// return trytb;
|
||||
// }
|
||||
|
||||
internal static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter) {
|
||||
if (string.IsNullOrEmpty(sql) || obj == null) return new T[0];
|
||||
var ttype = typeof(T);
|
||||
var type = obj.GetType();
|
||||
if (type == ttype) return new[] { (T)Convert.ChangeType(obj, type) };
|
||||
var ret = new List<T>();
|
||||
var ps = type.GetProperties();
|
||||
foreach (var p in ps) {
|
||||
if (sql.IndexOf($"{paramPrefix}{p.Name}", StringComparison.CurrentCultureIgnoreCase) == -1) continue;
|
||||
var pvalue = p.GetValue(obj);
|
||||
if (p.PropertyType == ttype) ret.Add((T)Convert.ChangeType(pvalue, ttype));
|
||||
else ret.Add(constructorParamter(p.Name, p.PropertyType, pvalue));
|
||||
}
|
||||
return ret.ToArray();
|
||||
}
|
||||
// internal static T[] GetDbParamtersByObject<T>(string sql, object obj, string paramPrefix, Func<string, Type, object, T> constructorParamter) {
|
||||
// if (string.IsNullOrEmpty(sql) || obj == null) return new T[0];
|
||||
// var ttype = typeof(T);
|
||||
// var type = obj.GetType();
|
||||
// if (type == ttype) return new[] { (T)Convert.ChangeType(obj, type) };
|
||||
// var ret = new List<T>();
|
||||
// var ps = type.GetProperties();
|
||||
// foreach (var p in ps) {
|
||||
// if (sql.IndexOf($"{paramPrefix}{p.Name}", StringComparison.CurrentCultureIgnoreCase) == -1) continue;
|
||||
// var pvalue = p.GetValue(obj);
|
||||
// if (p.PropertyType == ttype) ret.Add((T)Convert.ChangeType(pvalue, ttype));
|
||||
// else ret.Add(constructorParamter(p.Name, p.PropertyType, pvalue));
|
||||
// }
|
||||
// return ret.ToArray();
|
||||
// }
|
||||
|
||||
static Dictionary<Type, bool> dicExecuteArrayRowReadClassOrTuple = new Dictionary<Type, bool> {
|
||||
[typeof(bool)] = true,
|
||||
[typeof(sbyte)] = true,
|
||||
[typeof(short)] = true,
|
||||
[typeof(int)] = true,
|
||||
[typeof(long)] = true,
|
||||
[typeof(byte)] = true,
|
||||
[typeof(ushort)] = true,
|
||||
[typeof(uint)] = true,
|
||||
[typeof(ulong)] = true,
|
||||
[typeof(double)] = true,
|
||||
[typeof(float)] = true,
|
||||
[typeof(decimal)] = true,
|
||||
[typeof(TimeSpan)] = true,
|
||||
[typeof(DateTime)] = true,
|
||||
[typeof(DateTimeOffset)] = true,
|
||||
[typeof(byte[])] = true,
|
||||
[typeof(string)] = true,
|
||||
[typeof(Guid)] = true,
|
||||
[typeof(MygisPoint)] = true,
|
||||
[typeof(MygisLineString)] = true,
|
||||
[typeof(MygisPolygon)] = true,
|
||||
[typeof(MygisMultiPoint)] = true,
|
||||
[typeof(MygisMultiLineString)] = true,
|
||||
[typeof(MygisMultiPolygon)] = true,
|
||||
[typeof(BitArray)] = true,
|
||||
[typeof(NpgsqlPoint)] = true,
|
||||
[typeof(NpgsqlLine)] = true,
|
||||
[typeof(NpgsqlLSeg)] = true,
|
||||
[typeof(NpgsqlBox)] = true,
|
||||
[typeof(NpgsqlPath)] = true,
|
||||
[typeof(NpgsqlPolygon)] = true,
|
||||
[typeof(NpgsqlCircle)] = true,
|
||||
[typeof((IPAddress Address, int Subnet))] = true,
|
||||
[typeof(IPAddress)] = true,
|
||||
[typeof(PhysicalAddress)] = true,
|
||||
[typeof(NpgsqlRange<int>)] = true,
|
||||
[typeof(NpgsqlRange<long>)] = true,
|
||||
[typeof(NpgsqlRange<decimal>)] = true,
|
||||
[typeof(NpgsqlRange<DateTime>)] = true,
|
||||
[typeof(PostgisPoint)] = true,
|
||||
[typeof(PostgisLineString)] = true,
|
||||
[typeof(PostgisPolygon)] = true,
|
||||
[typeof(PostgisMultiPoint)] = true,
|
||||
[typeof(PostgisMultiLineString)] = true,
|
||||
[typeof(PostgisMultiPolygon)] = true,
|
||||
[typeof(PostgisGeometry)] = true,
|
||||
[typeof(PostgisGeometryCollection)] = true,
|
||||
[typeof(Dictionary<string, string>)] = true,
|
||||
[typeof(JToken)] = true,
|
||||
[typeof(JObject)] = true,
|
||||
[typeof(JArray)] = true,
|
||||
};
|
||||
// static Dictionary<Type, bool> dicExecuteArrayRowReadClassOrTuple = new Dictionary<Type, bool> {
|
||||
// [typeof(bool)] = true,
|
||||
// [typeof(sbyte)] = true,
|
||||
// [typeof(short)] = true,
|
||||
// [typeof(int)] = true,
|
||||
// [typeof(long)] = true,
|
||||
// [typeof(byte)] = true,
|
||||
// [typeof(ushort)] = true,
|
||||
// [typeof(uint)] = true,
|
||||
// [typeof(ulong)] = true,
|
||||
// [typeof(double)] = true,
|
||||
// [typeof(float)] = true,
|
||||
// [typeof(decimal)] = true,
|
||||
// [typeof(TimeSpan)] = true,
|
||||
// [typeof(DateTime)] = true,
|
||||
// [typeof(DateTimeOffset)] = true,
|
||||
// [typeof(byte[])] = true,
|
||||
// [typeof(string)] = true,
|
||||
// [typeof(Guid)] = true,
|
||||
// [typeof(MygisPoint)] = true,
|
||||
// [typeof(MygisLineString)] = true,
|
||||
// [typeof(MygisPolygon)] = true,
|
||||
// [typeof(MygisMultiPoint)] = true,
|
||||
// [typeof(MygisMultiLineString)] = true,
|
||||
// [typeof(MygisMultiPolygon)] = true,
|
||||
// [typeof(BitArray)] = true,
|
||||
// [typeof(NpgsqlPoint)] = true,
|
||||
// [typeof(NpgsqlLine)] = true,
|
||||
// [typeof(NpgsqlLSeg)] = true,
|
||||
// [typeof(NpgsqlBox)] = true,
|
||||
// [typeof(NpgsqlPath)] = true,
|
||||
// [typeof(NpgsqlPolygon)] = true,
|
||||
// [typeof(NpgsqlCircle)] = true,
|
||||
// [typeof((IPAddress Address, int Subnet))] = true,
|
||||
// [typeof(IPAddress)] = true,
|
||||
// [typeof(PhysicalAddress)] = true,
|
||||
// [typeof(NpgsqlRange<int>)] = true,
|
||||
// [typeof(NpgsqlRange<long>)] = true,
|
||||
// [typeof(NpgsqlRange<decimal>)] = true,
|
||||
// [typeof(NpgsqlRange<DateTime>)] = true,
|
||||
// [typeof(PostgisPoint)] = true,
|
||||
// [typeof(PostgisLineString)] = true,
|
||||
// [typeof(PostgisPolygon)] = true,
|
||||
// [typeof(PostgisMultiPoint)] = true,
|
||||
// [typeof(PostgisMultiLineString)] = true,
|
||||
// [typeof(PostgisMultiPolygon)] = true,
|
||||
// [typeof(PostgisGeometry)] = true,
|
||||
// [typeof(PostgisGeometryCollection)] = true,
|
||||
// [typeof(Dictionary<string, string>)] = true,
|
||||
// [typeof(JToken)] = true,
|
||||
// [typeof(JObject)] = true,
|
||||
// [typeof(JArray)] = true,
|
||||
// };
|
||||
|
||||
internal static ConcurrentDictionary<Type, _dicClassConstructorInfo> _dicClassConstructor = new ConcurrentDictionary<Type, _dicClassConstructorInfo>();
|
||||
internal static ConcurrentDictionary<Type, _dicTupleConstructorInfo> _dicTupleConstructor = new ConcurrentDictionary<Type, _dicTupleConstructorInfo>();
|
||||
internal class _dicClassConstructorInfo {
|
||||
public ConstructorInfo Constructor { get; set; }
|
||||
public PropertyInfo[] Properties { get; set; }
|
||||
}
|
||||
internal class _dicTupleConstructorInfo {
|
||||
public ConstructorInfo Constructor { get; set; }
|
||||
public Type[] Types { get; set; }
|
||||
}
|
||||
internal static (object value, int dataIndex) ExecuteArrayRowReadClassOrTuple(Type type, Dictionary<string, int> names, object[] row, int dataIndex = 0) {
|
||||
if (type.IsArray) return (GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
|
||||
var typeGeneric = type;
|
||||
if (typeGeneric.IsNullableType()) typeGeneric = type.GenericTypeArguments.First();
|
||||
if (typeGeneric.IsEnum ||
|
||||
dicExecuteArrayRowReadClassOrTuple.ContainsKey(typeGeneric))
|
||||
return (GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
|
||||
if (type.Namespace == "System" && (type.FullName == "System.String" || type.IsValueType)) { //值类型,或者元组
|
||||
bool isTuple = type.Name.StartsWith("ValueTuple`");
|
||||
if (isTuple) {
|
||||
if (_dicTupleConstructor.TryGetValue(type, out var tupleInfo) == false) {
|
||||
var types = type.GetFields().Select(a => a.FieldType).ToArray();
|
||||
tupleInfo = new _dicTupleConstructorInfo { Constructor = type.GetConstructor(types), Types = types };
|
||||
_dicTupleConstructor.AddOrUpdate(type, tupleInfo, (t2, c2) => tupleInfo);
|
||||
}
|
||||
var parms = new object[tupleInfo.Types.Length];
|
||||
for (int a = 0; a < parms.Length; a++) {
|
||||
var read = ExecuteArrayRowReadClassOrTuple(tupleInfo.Types[a], names, row, dataIndex);
|
||||
if (read.dataIndex > dataIndex) dataIndex = read.dataIndex;
|
||||
parms[a] = read.value;
|
||||
}
|
||||
return (tupleInfo.Constructor?.Invoke(parms), dataIndex);
|
||||
}
|
||||
return (dataIndex >= row.Length || (row[dataIndex] ?? DBNull.Value) == DBNull.Value ? null : GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
|
||||
}
|
||||
if (type == typeof(object) && names != null) {
|
||||
dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写
|
||||
var expandodic = (IDictionary<string, object>)expando;
|
||||
foreach (var name in names)
|
||||
expandodic.Add(name.Key, row[name.Value]);
|
||||
return (expando, names.Count);
|
||||
}
|
||||
//类注入属性
|
||||
if (_dicClassConstructor.TryGetValue(type, out var classInfo)== false) {
|
||||
classInfo = new _dicClassConstructorInfo { Constructor = type.GetConstructor(new Type[0]), Properties = type.GetProperties() };
|
||||
_dicClassConstructor.TryAdd(type, classInfo);
|
||||
}
|
||||
var value = classInfo.Constructor.Invoke(new object[0]);
|
||||
foreach(var prop in classInfo.Properties) {
|
||||
var tryidx = dataIndex;
|
||||
if (names != null && names.TryGetValue(prop.Name, out tryidx) == false) continue;
|
||||
var read = ExecuteArrayRowReadClassOrTuple(prop.PropertyType, names, row, tryidx);
|
||||
if (read.dataIndex > dataIndex) dataIndex = read.dataIndex;
|
||||
prop.SetValue(value, read.value, null);
|
||||
//FillPropertyValue(value, p.Name, read.value);
|
||||
//p.SetValue(value, read.value);
|
||||
}
|
||||
return (value, dataIndex);
|
||||
}
|
||||
// internal static ConcurrentDictionary<Type, _dicClassConstructorInfo> _dicClassConstructor = new ConcurrentDictionary<Type, _dicClassConstructorInfo>();
|
||||
// internal static ConcurrentDictionary<Type, _dicTupleConstructorInfo> _dicTupleConstructor = new ConcurrentDictionary<Type, _dicTupleConstructorInfo>();
|
||||
// internal class _dicClassConstructorInfo {
|
||||
// public ConstructorInfo Constructor { get; set; }
|
||||
// public PropertyInfo[] Properties { get; set; }
|
||||
// }
|
||||
// internal class _dicTupleConstructorInfo {
|
||||
// public ConstructorInfo Constructor { get; set; }
|
||||
// public Type[] Types { get; set; }
|
||||
// }
|
||||
// internal static (object value, int dataIndex) ExecuteArrayRowReadClassOrTuple(Type type, Dictionary<string, int> names, object[] row, int dataIndex = 0) {
|
||||
// if (type.IsArray) return (GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
|
||||
// var typeGeneric = type;
|
||||
// if (typeGeneric.IsNullableType()) typeGeneric = type.GenericTypeArguments.First();
|
||||
// if (typeGeneric.IsEnum ||
|
||||
// dicExecuteArrayRowReadClassOrTuple.ContainsKey(typeGeneric))
|
||||
// return (GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
|
||||
// if (type.Namespace == "System" && (type.FullName == "System.String" || type.IsValueType)) { //值类型,或者元组
|
||||
// bool isTuple = type.Name.StartsWith("ValueTuple`");
|
||||
// if (isTuple) {
|
||||
// if (_dicTupleConstructor.TryGetValue(type, out var tupleInfo) == false) {
|
||||
// var types = type.GetFields().Select(a => a.FieldType).ToArray();
|
||||
// tupleInfo = new _dicTupleConstructorInfo { Constructor = type.GetConstructor(types), Types = types };
|
||||
// _dicTupleConstructor.AddOrUpdate(type, tupleInfo, (t2, c2) => tupleInfo);
|
||||
// }
|
||||
// var parms = new object[tupleInfo.Types.Length];
|
||||
// for (int a = 0; a < parms.Length; a++) {
|
||||
// var read = ExecuteArrayRowReadClassOrTuple(tupleInfo.Types[a], names, row, dataIndex);
|
||||
// if (read.dataIndex > dataIndex) dataIndex = read.dataIndex;
|
||||
// parms[a] = read.value;
|
||||
// }
|
||||
// return (tupleInfo.Constructor?.Invoke(parms), dataIndex);
|
||||
// }
|
||||
// return (dataIndex >= row.Length || (row[dataIndex] ?? DBNull.Value) == DBNull.Value ? null : GetDataReaderValue(type, row[dataIndex]), dataIndex + 1);
|
||||
// }
|
||||
// if (type == typeof(object) && names != null) {
|
||||
// dynamic expando = new System.Dynamic.ExpandoObject(); //动态类型字段 可读可写
|
||||
// var expandodic = (IDictionary<string, object>)expando;
|
||||
// foreach (var name in names)
|
||||
// expandodic.Add(name.Key, row[name.Value]);
|
||||
// return (expando, names.Count);
|
||||
// }
|
||||
// //类注入属性
|
||||
// if (_dicClassConstructor.TryGetValue(type, out var classInfo)== false) {
|
||||
// classInfo = new _dicClassConstructorInfo { Constructor = type.GetConstructor(new Type[0]), Properties = type.GetProperties() };
|
||||
// _dicClassConstructor.TryAdd(type, classInfo);
|
||||
// }
|
||||
// var value = classInfo.Constructor.Invoke(new object[0]);
|
||||
// foreach(var prop in classInfo.Properties) {
|
||||
// var tryidx = dataIndex;
|
||||
// if (names != null && names.TryGetValue(prop.Name, out tryidx) == false) continue;
|
||||
// var read = ExecuteArrayRowReadClassOrTuple(prop.PropertyType, names, row, tryidx);
|
||||
// if (read.dataIndex > dataIndex) dataIndex = read.dataIndex;
|
||||
// prop.SetValue(value, read.value, null);
|
||||
// //FillPropertyValue(value, p.Name, read.value);
|
||||
// //p.SetValue(value, read.value);
|
||||
// }
|
||||
// return (value, dataIndex);
|
||||
// }
|
||||
|
||||
internal static void FillPropertyValue(object info, string memberAccessPath, object value) {
|
||||
var current = info;
|
||||
PropertyInfo prop = null;
|
||||
var members = memberAccessPath.Split('.');
|
||||
for (var a = 0; a < members.Length; a++) {
|
||||
var type = current.GetType();
|
||||
prop = type.GetProperty(members[a], BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);
|
||||
if (prop == null) throw new Exception(string.Concat(type.FullName, " 没有定义属性 ", members[a]));
|
||||
if (a < members.Length - 1) current = prop.GetValue(current);
|
||||
}
|
||||
prop.SetValue(current, GetDataReaderValue(prop.PropertyType, value), null);
|
||||
}
|
||||
internal static object GetDataReaderValue(Type type, object value) {
|
||||
if (value == null || value == DBNull.Value) return null;
|
||||
if (type.FullName == "System.Byte[]") return value;
|
||||
if (type.IsArray) {
|
||||
var elementType = type.GetElementType();
|
||||
var valueArr = value as Array;
|
||||
if (elementType == valueArr.GetType().GetElementType()) return value;
|
||||
var len = valueArr.GetLength(0);
|
||||
var ret = Array.CreateInstance(elementType, len);
|
||||
for (var a = 0; a < len; a++) {
|
||||
var item = valueArr.GetValue(a);
|
||||
ret.SetValue(GetDataReaderValue(elementType, item), a);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
if (type.IsNullableType()) type = type.GenericTypeArguments.First();
|
||||
if (type.IsEnum) return Enum.Parse(type, string.Concat(value), true);
|
||||
switch(type.FullName) {
|
||||
case "System.Guid":
|
||||
if (value.GetType() != type) return Guid.TryParse(string.Concat(value), out var tryguid) ? tryguid : Guid.Empty;
|
||||
return value;
|
||||
case "MygisPoint": return MygisPoint.Parse(string.Concat(value)) as MygisPoint;
|
||||
case "MygisLineString": return MygisLineString.Parse(string.Concat(value)) as MygisLineString;
|
||||
case "MygisPolygon": return MygisPolygon.Parse(string.Concat(value)) as MygisPolygon;
|
||||
case "MygisMultiPoint": return MygisMultiPoint.Parse(string.Concat(value)) as MygisMultiPoint;
|
||||
case "MygisMultiLineString": return MygisMultiLineString.Parse(string.Concat(value)) as MygisMultiLineString;
|
||||
case "MygisMultiPolygon": return MygisMultiPolygon.Parse(string.Concat(value)) as MygisMultiPolygon;
|
||||
case "Newtonsoft.Json.Linq.JToken": return JToken.Parse(string.Concat(value));
|
||||
case "Newtonsoft.Json.Linq.JObject": return JObject.Parse(string.Concat(value));
|
||||
case "Newtonsoft.Json.Linq.JArray": return JArray.Parse(string.Concat(value));
|
||||
case "Npgsql.LegacyPostgis.PostgisGeometry": return value;
|
||||
}
|
||||
if (type != value.GetType()) {
|
||||
if (type.FullName == "System.TimeSpan") return TimeSpan.FromSeconds(double.Parse(value.ToString()));
|
||||
return Convert.ChangeType(value, type);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
internal static string GetCsName(string name) {
|
||||
name = Regex.Replace(name.TrimStart('@'), @"[^\w]", "_");
|
||||
return char.IsLetter(name, 0) ? name : string.Concat("_", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
// internal static void FillPropertyValue(object info, string memberAccessPath, object value) {
|
||||
// var current = info;
|
||||
// PropertyInfo prop = null;
|
||||
// var members = memberAccessPath.Split('.');
|
||||
// for (var a = 0; a < members.Length; a++) {
|
||||
// var type = current.GetType();
|
||||
// prop = type.GetProperty(members[a], BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance);
|
||||
// if (prop == null) throw new Exception(string.Concat(type.FullName, " 没有定义属性 ", members[a]));
|
||||
// if (a < members.Length - 1) current = prop.GetValue(current);
|
||||
// }
|
||||
// prop.SetValue(current, GetDataReaderValue(prop.PropertyType, value), null);
|
||||
// }
|
||||
// internal static object GetDataReaderValue(Type type, object value) {
|
||||
// if (value == null || value == DBNull.Value) return null;
|
||||
// if (type.FullName == "System.Byte[]") return value;
|
||||
// if (type.IsArray) {
|
||||
// var elementType = type.GetElementType();
|
||||
// var valueArr = value as Array;
|
||||
// if (elementType == valueArr.GetType().GetElementType()) return value;
|
||||
// var len = valueArr.GetLength(0);
|
||||
// var ret = Array.CreateInstance(elementType, len);
|
||||
// for (var a = 0; a < len; a++) {
|
||||
// var item = valueArr.GetValue(a);
|
||||
// ret.SetValue(GetDataReaderValue(elementType, item), a);
|
||||
// }
|
||||
// return ret;
|
||||
// }
|
||||
// if (type.IsNullableType()) type = type.GenericTypeArguments.First();
|
||||
// if (type.IsEnum) return Enum.Parse(type, string.Concat(value), true);
|
||||
// switch(type.FullName) {
|
||||
// case "System.Guid":
|
||||
// if (value.GetType() != type) return Guid.TryParse(string.Concat(value), out var tryguid) ? tryguid : Guid.Empty;
|
||||
// return value;
|
||||
// case "MygisPoint": return MygisPoint.Parse(string.Concat(value)) as MygisPoint;
|
||||
// case "MygisLineString": return MygisLineString.Parse(string.Concat(value)) as MygisLineString;
|
||||
// case "MygisPolygon": return MygisPolygon.Parse(string.Concat(value)) as MygisPolygon;
|
||||
// case "MygisMultiPoint": return MygisMultiPoint.Parse(string.Concat(value)) as MygisMultiPoint;
|
||||
// case "MygisMultiLineString": return MygisMultiLineString.Parse(string.Concat(value)) as MygisMultiLineString;
|
||||
// case "MygisMultiPolygon": return MygisMultiPolygon.Parse(string.Concat(value)) as MygisMultiPolygon;
|
||||
// case "Newtonsoft.Json.Linq.JToken": return JToken.Parse(string.Concat(value));
|
||||
// case "Newtonsoft.Json.Linq.JObject": return JObject.Parse(string.Concat(value));
|
||||
// case "Newtonsoft.Json.Linq.JArray": return JArray.Parse(string.Concat(value));
|
||||
// case "Npgsql.LegacyPostgis.PostgisGeometry": return value;
|
||||
// }
|
||||
// if (type != value.GetType()) {
|
||||
// if (type.FullName == "System.TimeSpan") return TimeSpan.FromSeconds(double.Parse(value.ToString()));
|
||||
// return Convert.ChangeType(value, type);
|
||||
// }
|
||||
// return value;
|
||||
// }
|
||||
// internal static string GetCsName(string name) {
|
||||
// name = Regex.Replace(name.TrimStart('@'), @"[^\w]", "_");
|
||||
// return char.IsLetter(name, 0) ? name : string.Concat("_", name);
|
||||
// }
|
||||
// }
|
||||
//}
|
Reference in New Issue
Block a user