public static object ReflectionPropertySet( DbConfig config, object instance, DbClassInfoCache info, EagarDataRecord reader, ReflectionSetCacheModel cacheModel, DbAccessType?dbAccessType) { if (instance == null) { throw new ArgumentNullException(nameof(instance)); } if (info == null) { throw new ArgumentNullException(nameof(info)); } if (reader == null) { return(instance); } //Left c# property name and right the object to read from the reader //var listofpropertys = new Dictionary<string, object>(); var propertys = info.Propertys.ToArray(); var instanceOfFallbackList = new Dictionary <string, object>(); IDictionary <int, DbPropertyInfoCache> cache = new Dictionary <int, DbPropertyInfoCache>(); for (var i = 0; i < reader.FieldCount; i++) { info.Propertys.TryGetValue(info.SchemaMappingDatabaseToLocal(reader.GetName(i)), out var val); cache.Add(i, val); } //var containsKey = cacheModel?.Cache.ContainsKey(info.Type); //if (containsKey != true) //{ // for (var i = 0; i < reader.FieldCount; i++) // { // info.Propertys.TryGetValue(info.SchemaMappingDatabaseToLocal(reader.GetName(i)), out var val); // cache.Add(i, val); // } // if (containsKey == false) // { // cacheModel.Cache[info.Type] = cache; // } //} //if (containsKey == true) //{ // cache = cacheModel.Cache[info.Type]; //} for (var i = 0; i < reader.FieldCount; i++) { var property = cache[i]; var value = reader.GetValue(i); if (property != null) { var attributes = property.Attributes; var valueConverterAttributeModel = attributes.FirstOrDefault(s => s.Attribute is ValueConverterAttribute); //Should the SQL value be converted if (valueConverterAttributeModel != null) { var converter = valueConverterAttributeModel.Attribute as ValueConverterAttribute; //Create the converter and then convert the value before everything else var valueConverter = converter.CreateConverter(); value = valueConverter.Convert(value, property.PropertyInfo.PropertyType, converter.Parameter, CultureInfo.CurrentCulture); } var xmlAttributeModel = attributes.FirstOrDefault(s => s.Attribute is FromXmlAttribute); //should the Content be considerd as XML text? if (xmlAttributeModel != null) { //Get the XML text and check if its null or empty var xmlStream = value.ToString(); if (string.IsNullOrEmpty(xmlStream)) { continue; } //Check for List //if this is a list we are expecting other entrys inside if (property.CheckForListInterface()) { //target Property is of type list //so expect a xml valid list Take the first element and expect the propertys inside this first element var record = XmlDataRecord.TryParse(xmlStream, property.PropertyInfo.PropertyType.GetGenericArguments().FirstOrDefault(), false, config); var xmlDataRecords = record.CreateListOfItems(); var genericArguments = config.GetOrCreateClassInfoCache( property.PropertyInfo.PropertyType.GetGenericArguments().FirstOrDefault()); var enumerableOfItems = xmlDataRecords.Select( s => genericArguments .SetPropertysViaReflection(EagarDataRecord.WithExcludedFields(s), dbAccessType, config)).ToList(); object castedList; if (genericArguments.Type.IsClass && genericArguments.Type.GetInterface("INotifyPropertyChanged") != null) { var caster = typeof(DbCollection <>).MakeGenericType(genericArguments.Type) .GetConstructor(new[] { typeof(IEnumerable) }); castedList = caster.Invoke(new object[] { enumerableOfItems }); } else { var caster = typeof(NonObservableDbCollection <>).MakeGenericType(genericArguments.Type) .GetConstructor(new[] { typeof(IEnumerable) }); castedList = caster.Invoke(new object[] { enumerableOfItems }); } property.Setter.Invoke(instance, castedList); } else { var classInfo = config.GetOrCreateClassInfoCache(property .PropertyInfo .PropertyType); var xmlDataRecord = XmlDataRecord.TryParse(xmlStream, property.PropertyInfo.PropertyType, true, config); //the t var xmlSerilizedProperty = classInfo.SetPropertysViaReflection( EagarDataRecord.WithExcludedFields(xmlDataRecord), dbAccessType, config); property.Setter.Invoke(instance, xmlSerilizedProperty); } } else if (value is DBNull || value == null) { //property.Setter.Invoke(instance, new object[] {null}); } else if (value is IEnumerable <EagarDataRecord> navigationValue) { Type targetType; if (property.CheckForListInterface()) { targetType = property.PropertyType.GetElementType(); if (targetType == null) { targetType = property.PropertyType.GetGenericArguments().FirstOrDefault(); } } else { targetType = property.PropertyType; } var classInfo = config.GetOrCreateClassInfoCache(targetType); var enumeration = navigationValue.Select(subReader => { bool created; var source = CreateInstance(classInfo, subReader, out created); if (created) { return(source); } return(ReflectionPropertySet(config, source, classInfo, subReader, cacheModel, dbAccessType)); }).ToArray(); if (property.CheckForListInterface()) { var caster = typeof(DbCollection <>).MakeGenericType(targetType) .GetConstructor(new[] { typeof(IEnumerable) }); var castedList = caster.Invoke(new object[] { enumeration }); property.Setter.Invoke(instance, castedList); } else { property.Setter.Invoke(instance, enumeration.FirstOrDefault()); } } else { object changedType = value; if (property.PropertyType.IsInstanceOfType(value)) { changedType = value; } else { if (!DataConverterExtensions.ChangeType(ref changedType, property.PropertyInfo.PropertyType)) { continue; } } //if (value.GetType() != property.PropertyInfo.PropertyType) //{ // changedType = DataConverterExtensions.ChangeType(value, property.PropertyInfo.PropertyType); //} //else //{ // changedType = value; //} property.Setter.Invoke(instance, changedType); } } //This variable is null if we tried to find a property with the LoadNotImplimentedDynamicAttribute but did not found it else if (instanceOfFallbackList != null) { //no property found Look for LoadNotImplimentedDynamicAttribute property to include it if (instanceOfFallbackList.Any()) { instanceOfFallbackList.Add(reader.GetName(i), value); } else { var maybeFallbackProperty = propertys.FirstOrDefault( s => s.Value.Attributes.Any(e => e.Attribute is LoadNotImplimentedDynamicAttribute)); if (maybeFallbackProperty.Value != null) { instanceOfFallbackList = (Dictionary <string, object>)maybeFallbackProperty.Value.Getter.Invoke(instance); if (instanceOfFallbackList == null) { instanceOfFallbackList = new Dictionary <string, object>(); maybeFallbackProperty.Value.Setter.Invoke(instance, instanceOfFallbackList); } instanceOfFallbackList.Add(reader.GetName(i), value); } else { instanceOfFallbackList = null; } } } } //foreach (var item in listofpropertys) //{ // var property = propertys.FirstOrDefault(s => s.PropertyName == item.Key); //} return(instance); }
// /// <summary> // /// Creates a new Instance based on possible Ctor's and the given // /// <paramref name="reader" /> // /// </summary> // /// <returns></returns> // public object SetPropertysViaReflection(DbClassInfoCache type, EagarDataRecord reader, // Dictionary<int, DbPropertyInfoCache> mapping) // { // bool created; // var source = CreateInstance(type, reader, out created); // if (created) // { // return source; // } //#pragma warning disable 618 // return ReflectionPropertySet(Config, source, type, reader, mapping, DbAccessType); //#pragma warning restore 618 // } // /// <summary> // /// Creates an instance based on a Ctor injection or Reflection loading // /// or when using a MsCoreLib type direct enumeration // /// </summary> // /// <returns></returns> // public static object CreateInstance(DbClassInfoCache classInfo, // EagarDataRecord reader) // { // bool loaded; // return CreateInstance(classInfo, reader, out loaded); // } /// <summary> /// Creates an instance based on a Ctor injection or Reflection loading /// or when using a MsCoreLib type direct enumeration /// </summary> /// <returns></returns> public static object CreateInstance(DbClassInfoCache classInfo, EagarDataRecord reader, out bool fullLoaded, DbAccessType?accessType = null) { reader.WrapNulls = true; if (classInfo.IsMsCoreFrameworkType && reader.FieldCount == 1) { fullLoaded = true; var plainValue = reader.GetValue(0); return(plainValue); } if (classInfo.Factory != null) { fullLoaded = classInfo.FullFactory; var fullObject = classInfo.Factory(reader); return(fullObject); } var factories = classInfo.Constructors.Where(s => s.Arguments.Count == 1 && s.Arguments.First().Type.IsAssignableFrom(typeof(EagarDataRecord))) .ToArray(); var constructor = factories.FirstOrDefault(s => s.Attributes.Any(f => f.Attribute is ObjectFactoryMethodAttribute attribute && (!accessType.HasValue || attribute.TargetDatabase == accessType.Value))) ?? factories.FirstOrDefault(); //maybe single ctor with param if (constructor != null) { if (constructor.Arguments.Count == 1 && constructor.Arguments.First().Type.IsAssignableFrom(typeof(EagarDataRecord))) { classInfo.FullFactory = true; classInfo.Factory = s => constructor.Invoke(new object[] { s }); return(CreateInstance(classInfo, reader, out fullLoaded, accessType)); } } else { //check for a Factory method var factory = classInfo.Mehtods .FirstOrDefault(s => s.Attributes.Any(f => f.Attribute is ObjectFactoryMethodAttribute)); if (factory != null) { if (factory.MethodInfo.IsStatic) { var methodInfo = factory.MethodInfo as MethodInfo; if (methodInfo != null) { var returnType = methodInfo.ReturnParameter; if (returnType != null && returnType.ParameterType == classInfo.Type) { if (factory.Arguments.Count == 1 && factory.Arguments.First().Type.IsAssignableFrom(typeof(EagarDataRecord))) { classInfo.FullFactory = true; classInfo.Factory = s => factory.Invoke(new object[] { reader }); return(CreateInstance(classInfo, reader, out fullLoaded, accessType)); } } } } } } var emptyCtor = classInfo.Constructors.FirstOrDefault(f => !f.Arguments.Any()); if (emptyCtor == null) { throw new NotSupportedException( "You have to define ether an ObjectFactoryMethod as static or constructor with and IDataReader or an constructor without any arguments"); } classInfo.FullFactory = false; classInfo.Factory = s => emptyCtor.Invoke(); return(CreateInstance(classInfo, reader, out fullLoaded, accessType)); }