quinta-feira, 27 de janeiro de 2011

Mapear propriedades de um objeto para outro usando Reflection em C#

Muitas vezes você tem um groupo de objetos (POCO ou Models) que tem como função armazenar dados.  E muitas vezes você tem que mapear as propriedades de um objeto passando os valores de um para o outro.  Por exemplo, você tem um objeto chamado Cliente e você quer passar os valores para outro objeto Usuário que também possui as mesmas propriedades, você normalmente faria algo assim.


_cliente.Nome = _usuario.Nome;
_cliente.Endereco = _usuario.Endereco;

...

Se seu objeto tiver várias propriedades e se você precisar fazer isso em vários lugares fica sendo uma tarefa muito repetitiva.  E como programador nós aprendemos a refatorar o código para que tenha o mínimo possível de repetição.

Existe algumas soluções para esse problem, vou demonstrar como você usa Reflection in C# para fazer isso.

Considere os seguintes Methods.


 private static void AssignReflect(object fromObj, object toObj)
        {
            Type fromType = fromObj.GetType();
            Type toType = toObj.GetType();
            foreach (PropertyInfo fromInfo in fromType.GetProperties())
            {
                foreach (PropertyInfo toInfo in toType.GetProperties())
                {
                    //Assign values
                    if (fromInfo.Name.ToLower() == toInfo.Name.ToLower())
                    {
                        try
                        {
                            toInfo.SetValue(toObj, Convert.ChangeType(fromInfo.GetValue(fromObj, null),
                                            toInfo.PropertyType), null);
                            break;
                        }
                        catch (Exception e)
                        {
                            e.IsNull();
                            break;
                        }
                    }
 
                    //Clean Min SQL Datatime
                    CleanMinSQLDate(toObj, toInfo);
 
                    //Clean Null Strings
                    CleanNullStrings(toObj, toInfo);
                }
            }
        }
 
        private static void CleanMinSQLDate(object toObj, PropertyInfo toInfo)
        {
            if (toInfo.PropertyType == Type.GetType("System.DateTime"))
            {
                try
                {
                    DateTime dateValue = (DateTime)toInfo.GetValue(toObj, null);
                    if (dateValue.IsNull() || dateValue <= DateTime.MinValue)
                    {
                        toInfo.SetValue(toObj, Tools.GetMinSQLDate(), null);
                    }
                }
                catch (Exception ex)
                {
                    ex.IsNotNull();
                }
            }
        }
 
        private static void CleanNullStrings(object toObj, PropertyInfo toInfo)
        {
            if (toInfo.PropertyType == Type.GetType("System.String"))
            {
                try
                {
                    string stringValue = (string)toInfo.GetValue(toObj, null);
                    if (stringValue == null || stringValue == string.Empty)
                    {
                        toInfo.SetValue(toObj, string.Empty, null);
                    }
                }
                catch (Exception ex)
                {
                    ex.IsNotNull();
                }
            }
        }


O method AssignReflect recebe dois objetos como parameters, fonte e destino.
Em seguinte o tipo dos objetos e detectado.
Usando Reflection vamos fazer um loop nas propriedades dos dois objetos.
Comparamos os nomes das propriedades.
Se os nomes forem iguais, atribuir o valor de um objeto para outro, também usando Reflection.
Também esta incluido dois methods para ajudar, o CleanMinSqlDate para limpar as datas em formato SQL datetime, e method CleanNullStrings para limpar os strings nulls.

Para usar o method você teria que fazer o seguinte:


AssignReflect(_usuraio, _cliente);


Só isso mesmo.
Espero que ajude alguem.

Deylo Woo


p.s. outra opção é usar um API chamado AutoMapper
http://automapper.codeplex.com/wikipage?title=Getting%20Started&referringTitle=Documentation

Nenhum comentário:

Postar um comentário