Я реализовал общий шаблон репозитория и unitofwork. Я использовал базовые шаблоны, и они отлично работают. В проекте у меня есть требование, которое гласит: каждая таблица имеет несколько полей, которые содержат длинный, очень длинный текст, и пользователь должен иметь возможность выбирать и открывать любой из них. Поскольку каждое поле называлось по-разному, я решил использовать power ov generics с отражением, чтобы написать метод, который уменьшает имя таблицы и имя поля и возвращает его. метод, в обобщенном классе Repository, я написал, как выглядит это, кажется, работает правильноВызвать метод из базового класса с использованием отражения
public interface IRepository<T> where T : class
{
//other methods
string GetPropertyByName(int id, string property);
}
public class Repository<T> : IRepository<T> where T : class
{
// other methods. add, edit, delete...
public string GetPropertyByName(int id, string property)
{
T model = this.Get(id);
var obj = model.GetType().GetProperty(property).GetValue(model, null);
return obj != null ? obj.ToString() : null;
}
}
I creted классы модели для таблиц с помощью EF. Некоторые таблицы связывают напрямую genric-репозиторий, в то время как другие имеют отдельный интерфейс и его реализацию, поскольку они требуют дополнительного метода. Пример:
public interface ICompanyRepo : IRepository<COMPANY>
{
//some methods
}
public class CompanyRepo : Repository<COMPANY>, ICompanyRepo
{
//implementations of interface methods
}
И UOW реализация:
public interface IUnitOfWork
{
ICompanyRepo Company { get; }
IRepository<CURRENCY> Currency { get; }
}
public class UnitOfWork : IUnitOfWork
{
static DBEntities _context;
private UZMEDEXPORTEntities context
{
get
{
if (_context == null)
_context = new DBEntities();
return _context;
}
}
public UnitOfWork()
{
_context = context;
Company = new SP_CompanyRepo();
Currency = new Repository<CURRENCY>();
}
public ICompanyRepo Company { get; private set; }
public IRepository<CURRENCY> Currency { get; private set; }
}
У меня есть вопрос о вызове метода GetPropertyByName() в бизнес-уровне. Я попытался это:
public string GetHistory(string tableName, string fieldName, int id)
{
var prop = unitOfWork.GetType().GetProperty(tableName);
MethodInfo method;
method = prop.PropertyType.GetMethod("GetPropertyByName"); //try to find method
if(method == null) //if method not found search for interface which contains that method
method = prop.PropertyType.GetInterface("IRepository`1").GetMethod("GetPropertyByName");
var res = method.Invoke(prop, new object[] { id, fieldName });
return (string)res;
}
Который возвращает System.Reflection.TargetException. Насколько я понял, проблема заключается в реализации единицы исполнения. В моем методе вызова «prop» - это тип интерфейса (ICompanyRepo), но целью invoke должен быть класс реализации интерфейса, в данном случае «CompanyRepo». Я не мог найти, как определить тип класса реализации, и решить эту проблему. Любая помощь присваивается
Сторона примечания: «Общий метод» имеет очень специфический смысл в C# - код, показанный в сообщении, не показывает никаких общих методов - пожалуйста, отредактируйте сообщение, чтобы показать реальный общий (например, 'Foo()') или использовать другое слово ... –
Метод находится внутри общего класса, репозиторий, поэтому я подумал, что правильно также вызвать метод generic. Anywat вы правы, отредактировал ту часть вопроса @AlexeiLevenkov –
Я вижу. Пожалуйста, ознакомьтесь с инструкциями [MCVE] по отправке кода. Невозможно узнать, является ли тип «TEntity» конкретным (со странным соглашением об именах) или параметром родового типа на основе кода, предоставленного в сообщении. –