Estoy intentando crear un repositorio genérico para mis modelos. Actualmente tengo 3 modelos diferentes que no tienen ninguna relación entre ellos. (Contactos, Notas, Recordatorios).Acceso a propiedades mediante el parámetro de tipo genérico
class Repository<T> where T:class
{
public IQueryable<T> SearchExact(string keyword)
{
//Is there a way i can make the below line generic
//return db.ContactModels.Where(i => i.Name == keyword)
//I also tried db.GetTable<T>().Where(i => i.Name == keyword)
//But the variable i doesn't have the Name property since it would know it only in the runtime
//db also has a method ITable GetTable(Type modelType) but don't think if that would help me
}
}
En MainViewModel, me llaman el método de búsqueda de esta manera:
Repository<ContactModel> _contactRepository = new Repository<ContactModel>();
public void Search(string keyword)
{
var filteredList = _contactRepository.SearchExact(keyword).ToList();
}
Solución:
Finalmente fue con solución de expresión dinámica de Ray:
public IQueryable<TModel> SearchExact(string searchKeyword, string columnName)
{
ParameterExpression param = Expression.Parameter(typeof(TModel), "i");
Expression left = Expression.Property(param, typeof(TModel).GetProperty(columnName));
Expression right = Expression.Constant(searchKeyword);
Expression expr = Expression.Equal(left, right);
}
query = db.GetTable<TModel>().Where(Expression.Lambda<Func<TModel, bool>>(expr, param));
Pensando lateralmente, me gusta. Linq2Sql significará que probablemente necesiten usar algún procesamiento posterior para aplicar la interfaz a las clases. – Spence
El segundo enfoque (poner restricción en el método) me parece mejor, pero probablemente luego cambie el nombre del método SearchExactName. –
@Spence - hay dos formas de hacerlo; puede usar clases parciales para agregar el ': IName', o puede editar el DBML y establecer el tipo base global para entidades (si todos sus tipos deben implementarlo). –