none
Obtener propiedades de tipos anonimos RRS feed

  • Pregunta

  • Buenas a todos del foro, en la capa de datos tengo un método getDetail() que devuelve un tipo anónimo, y en la capa de presentación estoy intentando acceder a sus propiedades de la siguiente manera:

    Capa de presentación:

    private void loadDetail(int roleId)
    {
        var data = RoleBL.GetDetail(roleId);
        lblCode.Text = data.GetType().GetProperty("Code").GetValue(data, null).ToString();
        lblName.Text = data.GetType().GetProperty("Name").GetValue(data, null).ToString();
        lblDescription.Text = data.GetType().GetProperty("Description").GetValue(data, null).ToString();
        lblCreateUser.Text = data.GetType().GetProperty("CreateUser").GetValue(data, null).ToString();
        lblUpdateUser.Text = (data.GetType().GetProperty("UpdateUser").GetValue(data)).ToString();
        lblCreateDate.Text = data.GetType().GetProperty("CreateDate").GetValue(data, null).ToString();
        lblUpdateDate.Text = data.GetType().GetProperty("UpdateDate").GetValue(data, null).ToString();
    }

    Capa de acceso a datos

    public object getDetail(int roleId)
    {
        using (Context context = new Context())
        {
            var q = (from r in context.Roles
                    join u in context.Users on r.CreateUser equals u.UserId
                    where r.RoleId == roleId
                    select new
                    {
                        Code = r.Code,
                        Name = r.Name,
                        Description = r.Description,
                        CreateUser = u.FirstName,
                        UpdateUser = r.UpdateUser,
                        CreateDate = r.CreateDate,
                        UpdateDate = r.UpdateDate,
                    });
            return q;
        }
    }

    Mi pregunta es: 

    • Existe una mejor forma de trabajar con tipos anónimos para luego acceder a sus propiedades de manera más directa?

    lunes, 3 de marzo de 2014 14:41

Todas las respuestas

  • Existe una mejor forma de trabajar con tipos anónimos para luego acceder a sus propiedades de manera más directa?

    usando solo anonimos me temo que no, pero pdorias usar dynamic

    public List<dynamic> getDetail(int roleId)
    {
        using (Context context = new Context())
        {
            var q = from r in context.Roles
                    join u in context.Users on r.CreateUser equals u.UserId
                    where r.RoleId == roleId
                    select new
                    {
                        Code = r.Code,
                        Name = r.Name,
                        Description = r.Description,
                        CreateUser = u.FirstName,
                        UpdateUser = r.UpdateUser,
                        CreateDate = r.CreateDate,
                        UpdateDate = r.UpdateDate,
                    };
    				
            return q.ToList();
        }
    }

    por supuesto no tendras intelisense en el codigo, pero si escribes de forma correcta la propiedad funciona porque justamente para eso esta dynamic

    Nota: para suar dynamic necesitas .net 4 o superior

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    martes, 4 de marzo de 2014 17:24
  • Hola leandro, gracias por la respuesta. Intenté hacer: public List<dynamic> getDetail(int roleId) pero salió el siguiente error de sintaxis:

    Cannot implicitly convert type 'System.Collections.Generic.List<AnonymousType#1>' to 'System.Collections.Generic.List<dynamic>'

    Lo corregí poniendo de esta manera: public dynamic getDetail(int roleId) y los DataGridView cargan sin ningún problema. 

    El problema que tengo es cuando accedo a una propiedad del dynamic, ya que me sale el siguiente error:

    An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll
    Additional information: 'object' does not contain a definition for 'Name'

    A continuación le muestro el código de la aplicación:

    Capa de Acceso a Datos:

    public dynamic getDetail(int roleId)
    {
        using (Context context = new Context())
        {
            var q = (from r in context.Roles
                        join u in context.Users on r.CreateUser equals u.UserId
                        join u2 in context.Users on r.UpdateUser equals u2.UserId into temp
                        from u2 in temp.DefaultIfEmpty()
                        where r.RoleId == roleId
                        select new
                        {
                            Code = r.Code,
                            Name = r.Name,
                            Description = r.Description,
                            CreateUser = string.Concat(u.LastName, " ", u.FirstName),
                            UpdateUser = string.Concat(u2.LastName, " ", u2.FirstName),
                            CreateDate = r.CreateDate,
                            UpdateDate = r.UpdateDate,
                        }).FirstOrDefault();
            return q;
        }
    }

    Capa de Presentación:

    private void loadDetail(int roleId)
    {
        var dRoleDetail = RoleBL.GetDetail(roleId);
        lblName.Text = dRoleDetail.Name;
        lblDescription.Text = dRoleDetail.Description;
        lblCreateUser.Text = dRoleDetail.CreateUser;
        lblUpdateUser.Text = dRoleDetail.UpdateUser;
        lblCreateDate.Text = dRoleDetail.CreateDate.ToString();
        lblUpdateDate.Text = dRoleDetail.UpdateDate.ToString();
    }

    El objeto dRoleDetail si tiene datos: dRoleDetail { Code = 1, Name = SISTEMAS, Description = AREA DE SISTEMAS, CreateUser = JUAN JOSE, UpdateUser = MARTIN FLORES, CreateDate = 26/02/2014 17:00:20, UpdateDate = 26/02/2014 17:00:20 }

    martes, 4 de marzo de 2014 21:57
  • hola

    hay algo raro entre el mensaje de error y el codigo que proporcionas

    el error menciona una List<> pero en el codigl estas devolviendo un objeto simple ya que usas el FirstOrDefault()

    entonce no me explico como podria generarse ese mensaje si nunca usas una lista


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    miércoles, 5 de marzo de 2014 11:17
  • An unhandled exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll Additional information: 'object' does not contain a definition for 'Name'

    pero donde usas un object ?  debes dejar de usar object todo debe ser dynamic

    si usas object esta claro que no tendra la propiedad

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    miércoles, 5 de marzo de 2014 11:19
  • Hola leandro, gracias por la ayuda, el error:

    Cannot implicitly convert type 'System.Collections.Generic.List<AnonymousType#1>' to 'System.Collections.Generic.List<dynamic>'

    Salía cuando el método especificaba de esta manera: public List<dynamic> getDetail(int roleId) (en el código ya no lo estoy mostrando esta manera), pero ya lo corregí poniéndolo así: public dynamic getDetail(int roleId) este error ya no corregí.

    Pero el segundo error aun no lo puedo corregir, he revisado el código y no estoy utilizando un objeto en ninguna de las capas. A continuación te muestro las tres capas que interactuan para esta finalidad.

    Capa de acceso a datos:

    public dynamic getDetail(int roleId)
    {
        using (Context context = new Context())
        {
            var q = (from r in context.Roles
                        join u in context.Users on r.CreateUser equals u.UserId
                        join u2 in context.Users on r.UpdateUser equals u2.UserId into temp
                        from u2 in temp.DefaultIfEmpty()
                        where r.RoleId == roleId
                        select new
                        {
                            Code = r.Code,
                            Name = r.Name,
                            Description = r.Description,
                            CreateUser = string.Concat(u.LastName, " ", u.FirstName),
                            UpdateUser = string.Concat(u2.LastName, " ", u2.FirstName),
                            CreateDate = r.CreateDate,
                            UpdateDate = r.UpdateDate,
                        }).FirstOrDefault();
            return q;
        }
    }

    Capa de lógica de negocios:

    public static dynamic GetDetail(int roleId)
    {
        return rolRepository.getDetail(roleId);
    }

    Capa de presentación:

    private void loadDetail(int roleId)
    {
        dynamic dRoleDetail = RoleBL.GetDetail(roleId);
        lblName.Text = dRoleDetail.Name;
        lblDescription.Text = dRoleDetail.Description;
        lblCreateUser.Text = dRoleDetail.CreateUser;
        lblUpdateUser.Text = dRoleDetail.UpdateUser;
        lblCreateDate.Text = dRoleDetail.CreateDate.ToString();
        lblUpdateDate.Text = dRoleDetail.UpdateDate.ToString();
    }

    Al parecer creo que el método firstOrDefault() está devolviendo un objeto. Y no es necesario convertirlo a dynamic?

    Saludos gracias...

    miércoles, 5 de marzo de 2014 14:10
  • Al parecer creo que el método firstOrDefault() está devolviendo un objeto. Y no es necesario convertirlo a dynamic?

    firstOrDefault esta devolviendo un objeto anonimo, es por eso que usamos dynamic, porque sino no podrias devolverlo como resultado de la query

    imagino el error se produce aqui

    lblName.Text = dRoleDetail.Name;

    aunque es raro porque en el linq la propiedad la defines

    solo para descartar que pasa sino usas el  FirstOrDefault y devuelves una lista dynamic pero en la presentacion tomas el primer elemento

    si lo haces de ese elemento te deja tomar el Name

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    jueves, 6 de marzo de 2014 11:37
  • Hola leandro, gracias por la ayuda. Probé devolviendo una lista dynamic y funciona sin ningún problema. pero sigo con la duda:

    Porque dynamic no funciona con FirstOrDefault?

    Saludos, Gracias...

    jueves, 6 de marzo de 2014 13:46
  • Porque dynamic no funciona con FirstOrDefault?

    pues la verdad no me lo explico porque deberia funcionar correctamente

    si inspeccionas la variable que retorna el dynamic puedes ver que tiene contenido ?

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    jueves, 6 de marzo de 2014 14:25
  • si inspeccionas la variable que retorna el dynamic puedes ver que tiene contenido ?

    Cuando devuelvo con firstOrDefault si tiene datos el único problema que ocurre es que no reconoce las propiedades en el tiempo de ejecución. Esto es el contenido:

    dRoleDetail { Code = 1, Name = SISTEMAS, Description = AREA DE SISTEMAS, CreateUser = JUAN JOSE, UpdateUser = MARTIN FLORES, CreateDate = 26/02/2014 17:00:20, UpdateDate = 26/02/2014 17:00:20 }

    Saludos...

    jueves, 6 de marzo de 2014 15:00