Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

Difference between revisions of "CSharp:Automatismo caricamento Entità"

From Aino Wiki

Jump to: navigation, search
(Esempio 1)
 
(No difference)

Latest revision as of 16:50, 21 April 2021

Helper di trasformazione: DataRow-->CustomObject

Esempio 1

public static T GetEntity<T>(DataRow dr)
{
	bool columnCanNotCorrespond = true;
	return GetEntity<T>(dr, columnCanNotCorrespond);
}
/// <summary>
/// Riempie una Entità con i valori presenti in un DataRow automaticamente. 
/// Se un valore è NULLO inserirà il valore di default.
/// L'automatismo funzione solo se i nomi delle colonne (campi dal Db\DataRow) corrispondono ai nomi 
/// delle properties; se una Property non ha colonna del DataRow semplicemente è valorizzata al Default
/// (come dopo una istanzizione dell'oggetto mediante "new"). Se una colonna esiste ma non c'è la 
/// corrispondente proprietà la segnalazione dell'eccezione dipenderà dal flag: columnCanNotCorrespond
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dr"></param>
/// <param name="columnCanNotCorrespond">Se true, non scatta eccezione se c'è una colonna che non 
/// è corrispondente ad una Property</param>
/// <returns></returns>
public static T GetEntity<T>(DataRow dr, bool columnCanNotCorrespond)
{
	Type entityType = typeof(T);
	T entity = (T)entityType.Assembly.CreateInstance(entityType.FullName);
	string columnName = string.Empty;
	string strErrorMsg = string.Empty;
 
	try
	{
		if (columnCanNotCorrespond)
		{
			foreach (DataColumn dc in dr.Table.Columns)
			{
				columnName = dc.ColumnName;
				object columnValue = dr[columnName];
				//La Property Esiste?
				if (entity.GetType().GetProperty(columnName
												, BindingFlags.Public
													| BindingFlags.Instance
													| BindingFlags.IgnoreCase) != null)
				{
					//Assegnazione condizionata affinchè rimanga il valore di Default nel caso il valore da inserire sia nullo 
					if (columnValue != DBNull.Value)
					{
						PropertyInfo prop = entity.GetType().GetProperty(columnName
												 , BindingFlags.Public
													| BindingFlags.Instance
													| BindingFlags.IgnoreCase);
						if (prop.PropertyType.ToString() == "System.Boolean")
						{
							prop.SetValue(entity, bool.Parse(columnValue.ToString()), null);
						}
						else if (prop.PropertyType.ToString() == "System.DateTime")
						{
							prop.SetValue(entity, DateTime.Parse(columnValue.ToString()), null);
						}
						else if (prop.PropertyType.ToString() == "System.Int32")
						{
							prop.SetValue(entity, Int32.Parse(columnValue.ToString()), null);
						}
						//CUSTOM types, enum?
						else if (prop.PropertyType.ToString().Contains("Enum"))
						{
							//ToDo
						}
						else //Standard Type
						{
							prop.SetValue(entity, columnValue, null);
						}
					}
				}
			}
		}
		else //Scatterà eccezione se la Property non corrisponde alla colonna!
		{
			foreach (DataColumn dc in dr.Table.Columns)
			{
				columnName = dc.ColumnName;
				object columnValue = dr[columnName];
				//Assegnazione condizionata affinchè rimanga il valore di Default nel caso il valore da inserire sia nullo 
				if (columnValue != DBNull.Value)
				{
					entity.GetType().GetProperty(columnName
												 , BindingFlags.Public
													| BindingFlags.Instance
													| BindingFlags.IgnoreCase).SetValue(entity, columnValue, null);
				}
			}
		}
	}
	catch (Exception ex)
	{
		strErrorMsg = string.Format("Method GetEntity<T>, column '{0}'\r\n{1}", columnName, ex.Message);
		throw new Exception(strErrorMsg);
	}
	return (T)entity;
}

Esempio 2

private static Dictionary<string, PropertyInfo[]> _entitiesFields = new Dictionary<string, PropertyInfo[]>();
 
        /// <summary>
        /// Data una DataRow, restituisce un'entità
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="Entity"></param>
        /// <returns></returns>
        private static T FromDataRowToEntity<T>(DataRow dr) where T : new()
        {
            T result = new T();
 
            if (result != null && dr != null)
            {
                string fullyName = typeof(T).FullName;
                lock (_entitiesFields)
                {
                    if (!_entitiesFields.ContainsKey(fullyName))
                    {
                        // Ottengo tutti i campi della entity
                        _entitiesFields.Add(fullyName, result.GetType().GetProperties());
                    }
                }
 
                PropertyInfo[] properties = _entitiesFields[fullyName];
 
                if (properties != null)
                {
                    for (int i = 0; i < properties.Length; i++)
                    {
                        #region per ogni campo dell'entità, cerco il valore nella riga e glielo assegno
                        PropertyInfo property = properties[i];
                        string propertyName = property.Name;
                        if (dr.Table.Columns.Contains(propertyName))
                            property.SetValue(result, GetFieldValue(property, dr[propertyName]), null);
                        #endregion
                    }
                }
            }
            return result;
        }
 
        /// <summary>
        /// Data una DataTable, restituisce una collezione di entità
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        private static List<T> FromDataTableToListOfEntity<T>(DataTable dt) where T : new()
        {
            List<T> tmp_list = new List<T>();
            if (dt != null)
            {
                foreach (DataRow dr in dt.Rows)
                {
                    T toAdd = FromDataRowToEntity<T>(dr);
                    if (toAdd != null) tmp_list.Add(toAdd);
                }
            }
 
            return tmp_list;
        }

Trasformazione Lista di Entità in DataTable

/// <summary>
/// Converts a Generic List into a DataTable.
/// </summary>
/// <param name="genericList">Generic list</param>
/// <returns>DataTable object</returns>
public static DataTable GenericListToDataTable(object genericList)
{
	DataTable dataTable = null;
	Type listType = genericList.GetType();
 
	if (listType.IsGenericType & (genericList != null))
	{
		//determine the underlying type the List<> contains
		Type elementType = listType.GetGenericArguments()[0];
 
		//create empty table -- give it a name in case
		//it needs to be serialized
		dataTable = new DataTable(elementType.Name + "List");
 
		//define the table -- add a column for each public
		//property or field
		MemberInfo[] memberInfos = elementType.GetMembers(BindingFlags.Public | BindingFlags.Instance);
		foreach (MemberInfo memberInfo in memberInfos)
		{
			if (memberInfo.MemberType == MemberTypes.Property)
			{
				PropertyInfo propertyInfo = memberInfo as PropertyInfo;
				if (IsNullableType(propertyInfo.PropertyType))
				{
					dataTable.Columns.Add(propertyInfo.Name, new NullableConverter(propertyInfo.PropertyType).UnderlyingType);
				}
				else
				{
					dataTable.Columns.Add(propertyInfo.Name, propertyInfo.PropertyType);
				}
			}
			else if (memberInfo.MemberType == MemberTypes.Field)
			{
				FieldInfo fieldInfo = memberInfo as FieldInfo;
				dataTable.Columns.Add(fieldInfo.Name, fieldInfo.FieldType);
			}
		}
 
		//populate the table
		IList listData = genericList as IList;
		foreach (object record in listData)
		{
			int index = 0;
			object[] fieldValues = new object[dataTable.Columns.Count];
			foreach (DataColumn columnData in dataTable.Columns)
			{
				MemberInfo memberInfo = elementType.GetMember(columnData.ColumnName)[0];
				if (memberInfo.MemberType == MemberTypes.Property)
				{
					PropertyInfo propertyInfo = memberInfo as PropertyInfo;
					fieldValues[index] = propertyInfo.GetValue(record, null);
				}
				else if (memberInfo.MemberType == MemberTypes.Field)
				{
					FieldInfo fieldInfo = memberInfo as FieldInfo;
					fieldValues[index] = fieldInfo.GetValue(record);
				}
				index += 1;
			}
			dataTable.Rows.Add(fieldValues);
		}
	}
	return dataTable;
}
 
/// <summary>
/// Check if a type is Nullable type
/// </summary>
/// <param name="propertyType">Type to be checked</param>
/// <returns>true/false</returns>
/// <remarks></remarks>
private static bool IsNullableType(Type propertyType)
{
	return (propertyType.IsGenericType) && (object.ReferenceEquals(propertyType.GetGenericTypeDefinition(), typeof(Nullable<>)));
}

Helper mapping e copia: CustomObject1-->CustomObject2

Versione semplificata:

private static T MapCustom<T>(object entitySource)
{
	Type entityDestType = typeof(T);
	Type entitySourceType = entitySource.GetType();
	T entityDestination = (T)entityDestType.Assembly.CreateInstance(entityDestType.FullName);
 
	foreach (PropertyInfo piSrc in entitySourceType.GetProperties(BindingFlags.FlattenHierarchy // Mamber static and public, nested type are not returned
																))
	{
		if (piSrc.CanRead)
		{
			foreach (PropertyInfo piDst in entityDestType.GetProperties(BindingFlags.FlattenHierarchy // Nested type are not returned
																		))
			{
				if (piSrc.Name.Equals(piDst.Name, StringComparison.InvariantCultureIgnoreCase))
				{
					if (piSrc.PropertyType == piDst.PropertyType)
					{
						if (piDst.CanWrite)
						{
							// value
							object srcVal = piSrc.GetValue(entitySource, null);
							piDst.SetValue(entityDestination, srcVal, null);
						}
					}
					else
					{
						// Managing nullable values ....
					}
				}
			}
		}
	}
	return (T)entityDestination;
}

Versione compatta e realistica:

private T MapCustom<T>(object entitySource)
{
	Type entityDestType = typeof(T);
	Type entitySourceType = entitySource.GetType();
	T entityDestination = (T)entityDestType.Assembly.CreateInstance(entityDestType.FullName);
	string srcPropertyName = string.Empty;
	string csvNotMatchingPropertiesName = string.Empty; // Not used BUT may be logged for debug purpose!
 
	try
	{
		// Arrray of member static and public, nested type are not returned:
		PropertyInfo[] arrPropertyInfoDest = entityDestType.GetProperties() //BindingFlags.FlattenHierarchy
															.Where(pd => pd.CanWrite).ToArray();
 
		// For each member static and public, nested type are not returned:
		foreach (PropertyInfo piSrc in entitySourceType.GetProperties() //BindingFlags.FlattenHierarchy
															.Where(ps => ps.CanRead))
		{
			srcPropertyName = piSrc.Name;
			PropertyInfo piDst = arrPropertyInfoDest.SingleOrDefault(i => i.Name.Equals(piSrc.Name,
																			   StringComparison.InvariantCultureIgnoreCase)
																		   && i.PropertyType == piSrc.PropertyType);
			if (piDst != null)
			{
				// Set value:
				object srcVal = piSrc.GetValue(entitySource, null);
				piDst.SetValue(entityDestination, srcVal, null);
			}
			else
			{
				csvNotMatchingPropertiesName += string.Format("{0},", srcPropertyName);
			}
		}
	}
	catch (Exception ex)
	{
		priceListManager.Error(string.Format("Error on source property '{0}'.\r\n{1}", 
											srcPropertyName, ex.Message), 
								ex);
		// ToDo Manage exception!
	}
	return (T)entityDestination;
}

Mappa e Links


C# | Helper DB


Esempio completo Helper