none
Expressões genéricas - Criando objetos MemberExpression para tipos complexos RRS feed

  • Pergunta

  • Prezados,

     

         Gostaria de uma ajuda para resolver o seguinte problema:

          Em uma classe de persistência genêrica, existe métodos para a construção de expressões (Expression<Func<T, bool>>) para a realização e construção de filtros em coleções que implementam a interface IEnumerable e/ou IQuerable.

    Em determinados momentos, é necessário que seja criado um objeto MemberExpression para a criação da expressão, quando o acesso é realizado em propriedades de objetos comuns (tipos primitivos) o objeto MemberExpression é criado sem problemas, contudo, quando o acesso é feito em objetos completos (referências a outras classes) o objeto MemberExpression é criado mas não é passível de utilização, uma vez que o objeto parameter (ParameterExpression) deixa de ser referenciado ou perde o bind, levantando a excessão "The parameter 'e' was not bound in the specified LINQ to Entities query expression".

    Segue o método implementado para criação do objeto MemberExpression, estou usando o Visual Studio 2010, .NET Framework 4.0 e o EntityFramework

     

    public MemberExpression GetMemberExpression(string propertyName, out PropertyInfo propertyInfo, MemberExpression memberExpression = null)
            {
                ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "e");       


                string propertyPartName = string.Empty;
                propertyInfo = null;

                foreach (string s in propertyName.Split('.'))
                {
                    if (memberExpression == null)
                    {
                        propertyPartName = s;

                        if (String.IsNullOrEmpty(propertyName))
                        {
                            propertyInfo = GetKeyProperty();
                            memberExpression = Expression.MakeMemberAccess(parameterExpression, propertyInfo);
                        }
                        else
                        {
                            propertyInfo = GetPropertyInfo(s);
                            memberExpression = Expression.MakeMemberAccess(parameterExpression, propertyInfo);
                        }
                    }
                    else
                    {
                        propertyPartName += "." + s;
                        propertyInfo = GetPropertyInfo(propertyPartName);

                        memberExpression = Expression.MakeMemberAccess(memberExpression, propertyInfo);                   
                    }
                }

                return memberExpression;
            }

     

    protected PropertyInfo GetPropertyInfo(string propertyName)
            {
                PropertyInfo piReturn = null;

                PropertyInfo[] propertyInfoCollection = typeof(T).GetProperties();

                foreach (PropertyInfo propertyInfo in propertyInfoCollection)
                {
                    if (propertyInfo.Name.ToUpper().Equals(propertyName.Split('.')[0].ToUpper()))
                    {
                        if (propertyName.IndexOf('.') > 0)
                        {
                            if (propertyInfo.PropertyType.BaseType == typeof(EntityObject))
                            {
                                piReturn = GetPropertyInfoChild(propertyName, propertyInfo);
                            }
                        }
                        else
                        {
                            piReturn = propertyInfo;
                        }
                        break;
                    }
                }

                if (piReturn == null && propertyInfoCollection != null)
                    piReturn = propertyInfoCollection[0];

                return piReturn;
            }

     

    protected PropertyInfo GetPropertyInfoChild(string mypropertyName, PropertyInfo entityobj)
            {
                PropertyInfo piReturn = null;

                PropertyInfo[] propertyInfoCollection = entityobj.PropertyType.GetProperties();

                foreach (PropertyInfo propertyInfo in propertyInfoCollection)
                {
                    if (propertyInfo.Name.ToUpper().Equals(mypropertyName.Split('.')[1].ToUpper()))
                    {
                        if (mypropertyName.IndexOf('.') > 0)
                        {
                            if ((entityobj.PropertyType.Name + "." + propertyInfo.Name).ToUpper().Equals(mypropertyName.ToUpper()))
                            {
                                piReturn = propertyInfo;
                            }

                            if (propertyInfo.PropertyType == typeof(EntityObject))
                            {
                                piReturn = GetPropertyInfoChild(mypropertyName.Substring(mypropertyName.IndexOf('.')), propertyInfo);
                            }

                            break;
                        }
                    }
                }

                if (piReturn == null && propertyInfoCollection != null)
                    piReturn = propertyInfoCollection[0];

                return piReturn;
            }

     

    public PropertyInfo GetKeyProperty<T>()
            {
                PropertyInfo[] properties = typeof(T).GetProperties();
                foreach (PropertyInfo property in properties)
                {
                    EdmScalarPropertyAttribute attrib = property.GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false).FirstOrDefault() as EdmScalarPropertyAttribute;
                    if (attrib != null && attrib.EntityKeyProperty)
                        return property;
                }
                return null;
            }

     

    Caso possam ajudar, agradeço a atenção.

     

    Gustavo Henrique



    • Editado GUSTAVOGHDD quarta-feira, 9 de novembro de 2011 16:39
    quarta-feira, 9 de novembro de 2011 16:34