Как создать общий метод из двух похожих, но разных методов?
у меня есть два похожих метода, которые в основном делают то же самое только с разными объектами. Каков наилучший способ сделать общий метод из этого, если это возможно?
два объекта:
public class StoreObject {
int Key;
string Address;
string Country;
int Latitude;
int Longitude;
}
public class ProjectObject {
int ProjectKey;
string Address;
string Description;
}
два метода, которые я потенциально хочу сделать в родовую:
public StoreObject GetStoreByKey(int key)
{
using (DBEntities dbe = new DBEntities())
{
StoreObject so = new StoreObject();
var storeObject = (from s in dbe.StoreTables
where s.Key == key
select s).First();
so.Key = storeObject.key;
so.Address = storeObject.address;
so.Country = storeObject.country;
so.Latitude = storeObject.latitude;
so.Longitude = storeObject.longitude;
return so;
}
}
public ProjectObject GetProjectByKey(int projectKey)
{
using (DBEntities dbe = new DBEntities())
{
ProjectObject po = new ProjectObject();
var projectObject = (from p in dbe.ProjectTables
where p.ProjectKey == projectKey
select p).First();
po.Key = projectObject.p_key;
po.Address = projectObject.p_address;
po.Description = projectObject.p_description;
return po;
}
}
Я должен отметить, что:
- У меня нет контроля над тем, как называются поля таблицы (т. е. p_description).
- StoreTable в БД, например, может иметь другие свойства (например, телефон, почтовый индекс и т. д.), Но меня интересует только то, что я показал в коде.
- То же самое касается ProjectTable.
4 ответов
ну, сложная часть заключается в том, что ваши сущности имеют разные свойства, поэтому использование дженериков для заполнения различных свойств в одном методе не будет стоить того. Но вы можете вернуть весь объект, а затем просто использовать свойства вас интересуют.
public T GetEntityByKey<T>(int key)
{
using (DBEntities dbe = new DBEntities())
{
return = dbe.StoreTables.Set<T>.Find(new object[] {key});
}
}
и использовать его
StoreObject so = GetEntityByKey<StoreObject>(123);
if(so != null)
{
int lat = so.Latitude;
}
вы действительно можете абстрагировать возвращаемый тип и разложить на множители using
, но для остального вам понадобится либо переключатель запрошенного типа, либо отражение для передачи в полях для извлечения в качестве параметров и запроса DB для использования.
первое было бы плохой практикой и мало что приносит уравнению, а последнее дорого и может стать грязным.
Это не очень хороший кандидат для дженериков, если у вас много таких подобных методов, в этом случае Я бы предпочел рефлексивный подход.
HTH,
Баб.
очень маловероятно, что это вся ваша "единица работы" и, следовательно, использование свежего DBEntities()
контекст в каждом из этих методов, вероятно, является корнем вашей проблемы здесь.
создание Repository
класс, который содержит экземпляр DBEntities
класс для одного веб-запроса (или любой другой единицы запроса, который у вас есть в вашем приложении), и который имеет эти методы в нем, был бы лучшим подходом к устранению дубликата кода здесь. Объем - это вне этих методов и, надеюсь, привязан к вашему веб-запросу или другой единице времени.
в качестве опции вместо создания нового класса вы также можете расширить DBEntities
частичный класс для включения таких методов (при условии, что это сгенерированный код).
у вас по существу есть две разные функции в каждом методе:
- запрос субъекта
- сопоставьте эту сущность с другим типом
первая часть была рассмотрена Стивом Мэллори.
во второй части можно использовать структуру сопоставления для обработки копирования значений из одного экземпляра в другой. Поскольку имена каждого типа не совпадают, вам нужно рассказать ему, как сопоставить имена (в вашем примере, добавив " p_ " и сделав это нижний регистр.) Одной из возможностей было бы Выделяют Картографа.
Если вы были чтобы исключить всю общность, это было бы что-то вроде:
public TResult GetById<TResult, TEntity>(int id)
{
using (DBEntities dbe = new DBEntities())
{
T result = dbe.StoreTables.Set<T>.Find(new object[] {key});
var mapper = ObjectMapperManager.DefaultInstance
.GetMapper<TEntity, TResult>(
new DefaultMapConfig().MatchMembers((m1, m2) => "p_" + m1.ToLower() == m2));
return mapper.Map(result);
}
}