2010-05-21 50 views
9

Tengo un método que cuenta el número de contactos de cada proveedor, cliente y el fabricante tiene (este es un escenario para tratar de hacer la explicación más fácil!)C# acceder a las propiedades de un objeto genérico

Los modelos son creados por Linq a las clases de SQL. Cada proveedor, cliente y el fabricante puede haber uno o más contactos

public int CountContacts<TModel>(TModel entity) where TModel : class 
{ 
    return entity.Contacts.Count(); 
} 

Lo anterior, por supuesto, no funciona, debido a que la 'entidad' es genérica y no sabe si tiene la propiedad 'Contactos'. ¿Alguien puede ayudar con cómo lograr esto?

Respuesta

6

Una manera fácil sería adjuntar una interfaz a las clases que se implementan en el genérico.

public int CountContacts<TModel>(TModel entity) where TModel : IContacts 


interface IContacts 
{ 
    IList<Contact> Contacts {get;} //list,Ilist,ienumerable 
} 
+0

+1 Excepto que no debe devolver la lista - preferiblemente IList <> o quizás incluso IEnumerable <> – n8wrl

+0

Buen punto. Estaba escribiendo rápido y no lo pensé bien. – kemiller2002

+0

El problema con esto es que las clases de LINQ a SQL usan EntitySets para tal fin, y la propiedad de Contactos con el tipo EntitySet no implementará la propiedad de la interfaz, por lo que deberá implementarla manualmente en todas las clases. – Venemo

3

Una forma de imponer un contratodonde proveedores, clientes y proveedores de equipos originales deben contener una propiedad Contacts es con interfaces. Haga que cada entidad implementar una interfaz que contiene la propiedad Contacts:

interface IContactable 
{ 
    IEnumerable<Contact> Contacts {get;} 
} 


public int CountContacts<TModel>(TModel entity) where TModel : class, IContactable 
{ 
    return entity.Contacts.Count(); 
} 
0

Otra forma es crear una interfaz solo para el conteo. Puedes llamarlo ICountable.

De MSDN

public interface ICountable<out T> 
{ 
    int Count{ get; } 
} 
public class MyCollection : ICountable<string>, ICountable<FileStream> 
{ 
    int ICountable<string>.Count 
    { 
     get { return 1; } 
    } 
    int ICountable<FileStream>.Count 
    { 
     get { return 2; } 
    } 
} 
1

Todas las respuestas hasta el momento son correctas, pero también hay que señalar que la razón de su código no compila es porque los tipos TModel no tienen nada en común. Al especificar una clase base común o una interfaz que todos implementan con su propiedad 'Contactos', su código funcionará.

0

Existen varias soluciones al problema.

  • Heredar la misma clase abstracta o implementar la misma interfaz con las entidades. (Los demás agotaron todas las soluciones posibles con esto.)
  • Si está utilizando .NET 4, la palabra clave dynamic puede ser la solución más económica.

Por ejemplo:

public int CountContacts(dynamic entity) 
{ 
    return entity.Contacts.Count(); 
} 

Esto significa que entity no será evaluado hasta el tiempo de ejecución, y si le toca para llamar al método en un objeto que no tiene una propiedad Contacts, arrojará usted una excepción.

Cuestiones relacionadas