0

Мне было интересно, можно ли сопоставить тип модели с типом репозитория с C#/ASP.NET. Как вы видите, я пытаюсь реализовать шаблон репозитория/единицы работы. Пример реализации приведен ниже:Тип модели карты ASP.NET для типа репозитория?

public class UnitOfWork : IDisposable 
{ 
    private SchoolContext context = new SchoolContext(); 
    private DepartmentRepository departmentRepository; 
    private CourseRepository courseRepository; 

    public DepartmentRepository DepartmentRepository 
    { 
     get 
     { 

      if (this.departmentRepository == null) 
      { 
       this.departmentRepository = new DepartmentRepository(context); 
      } 
      return departmentRepository; 
     } 
    } 

    public CourseRepository CourseRepository 
    { 
     get 
     { 

      if (this.courseRepository == null) 
      { 
       this.courseRepository = new CourseRepository(context); 
      } 
      return courseRepository; 
     } 
    } 

имеет проблему, однако, что UnitOfWork нужно держать длинный список свойств для каждого типа хранилища. В этом примере это не так уж плохо, так как существует только два типа сущностей (отдел, курс) с двумя соответствующими репозиториями (репозиторий депонирования и репозиторий курсов). Но по мере роста размера приложения класс UnitOfWork быстро становится большим и беспорядочным с десятками или даже сотнями свойств, это будет не что иное, как класс богов.

Что бы я хотел, это нечто более общее, например, общий метод GetRepository(), который сопоставляет тип модели с объектом репозитория. Ниже псевдокод показывает, что я хочу:

// definition 
public TRepository GetRepository<TModel>(){ // pending implementation } 

// use-case 
var departmentRepository = UnitOfWork.GetRepository<TModel>(); 

Так как я могу написать такой код, который отображает тип модели на объект хранилища? Я боюсь, что AutoMapper не будет работать, поскольку он отображает только конкретные реализации, а не общие типы. Как вы думаете? Как вы подходите к этой проблеме, когда условием является не жесткое кодирование каждой реализации репозитория как свойств в единице работы?

+1

Удалите репозитории из UnitOfWork. Внесите UoW в репозитории и получите объекты сущности из контекста. – Jasen

+1

Выглядит немного как работа для инъекции зависимостей и инверсии управления. Вы зарегистрировали бы все модели и соответствующие ассоциации репозитория в своем загрузочном устройстве IOC ... – Theo

+0

Вы можете написать свой собственный инструмент для решения этой проблемы –

ответ

0

Вы можете определить метод расширения, как это:

public static class Mapper 
{ 
    public static T Map<T>(Object source) where T : class 
    { 
     var instance = Activator.CreateInstance<T>(); 

     foreach (var property in typeof(T).GetProperties()) 
     { 
      if (property.CanRead) 
      { 
       var sourceProperty = source.GetType().GetProperty(property.Name); 

       if (sourceProperty == null) 
       { 
        continue; 
       } 

       var value = sourceProperty.GetValue(source); 

       property.SetValue(instance, value); 
      } 
     } 

     return instance; 
    } 
} 

Если вы хотите отобразить один класс от другого:

var foo = Mapper.Map<CustomerViewModel>(new Customer { CustomerID = "ACME", CompanyName = "Acme Corp.", ContactName = "Jhon Doe" }); 

Выход:

{CustomerViewModel} НазваниеКомпании: " Acme Corp. " CustomerID: «ACME»

Если у вас есть следующие классы:

public class Customer 
{ 
    public String CustomerID { get; set; } 

    public String CompanyName { get; set; } 

    public String ContactName { get; set; } 
} 

public class CustomerViewModel 
{ 
    public String CustomerID { get; set; } 

    public String CompanyName { get; set; } 
} 

Кроме того, это основная идея, которую вы можете улучшить этот метод расширения для отображения из динамического объекта (ExpandoObject), словарь (словарь < String, Object >) и создайте таблицу сопоставления для лучшей производительности при сопоставлении коллекции (большие коллекции элементов).

Этот метод также поддерживает анонимные объекты.

Пожалуйста, дайте мне знать, если этот ответ полезен, мы можем улучшить алгоритм в соответствии с вашими требованиями.

+0

Ну, я знаю, как сопоставить модель домена с моделью уже, просто используйте automapper, и он работает. Вопрос, который у меня есть, заключается в том, как сопоставить два объекта с несвязанными свойствами/композициями, но с аналогичным соглашением об именах. Допустим, у меня есть модель домена под названием «UserModel», и ее репозиторий называется «UserRepository», я хочу сопоставить «UserModel» с «UserRepository». Как я могу это достичь? –

+0

В этом случае имя классов не имеет значения только для имен свойств; вы пробовали модифицировать этот кусок кода для поддержки лямбда-выражений, возможно, я пропустил что-то в вашем вопросе, и вы хотите отображать свойства с разными именами –