Как динамически переключаться между репозиторием XML и SQL в веб-службе/веб-API?

У меня есть веб-служба для выполнения операции CRUD. У меня есть интерфейс IProductRepository, реализованный XMLProductRepository и SQLProductRepository.

Теперь я использую экземпляр репозитория в своем контроллере веб-службы для вызова операций Get/Put/POST и Delete, которые определены соответственно в XMLRepository и SQLRepository. Но я немного запутался в том, как динамически переключаться между этими двумя репозиториями, поскольку я хочу, чтобы моя база данных веб-сервиса не зависела

public interface IProductRepository
{
    IEnumerable<Product> GetAll();
    Product Get(int id);
    Product Add(Product item);
    void Remove(int id);
    bool Update(Product item);
}

public class XMLProductRepository : IProductRepository
{

    public XMLProductRepository() {}
    public IEnumerable<Product> GetAll() {}
    public Product Get(int id) {}
    public Product Add(Product item) {}
    public void Remove(int id) {}
    public bool Update(Product item) {}
}

public class SQLProductRepository : IProductRepository
{
    public SQLProductRepository() {}
    public IEnumerable<Product> GetAll() {}
    public Product Get(int id) {}
    public Product Add(Product item) {}
    public void Remove(int id) {}
    public bool Update(Product item) {}
}   

public class ProductController : ApiController
{

   static readonly IProductRepository repository = new XMLProductRepository();

   // REST OF THE CODE AND IMPLEMENTATION HERE...
   // using the repository object

}        

Вопрос в том, как мне сделать его здесь динамическим, вместо того, чтобы определять конкретный объект репозитория в контроллере? Или вопрос в том, могу ли я сделать это для этого WEB API?

Позвольте мне добавить дополнительные детали к Вопросу. Спасибо Дилли-О за указание на это.

У меня есть требование: «Источники являются взаимоисключающими. В любой момент времени служба выбирает информацию только из одного источника, будь то XML или SQL. Служба должна иметь возможность переключаться между источниками без ведома клиента. В дополнение к этому веб-API службы. не должен меняться всякий раз, когда меняется мой источник».


person vran    schedule 17.06.2014    source источник
comment
Найдите минутку, чтобы прочитать справку по редактированию в справочном центре. Форматирование на Stack Overflow отличается от форматирования на других сайтах. Чем лучше выглядит ваш пост, тем проще пользователям будет вам помочь.   -  person gunr2171    schedule 17.06.2014
comment
Вы бы создали экземпляр репозитория только тогда, когда знаете, какой тип вам нужен.   -  person Neil Smith    schedule 17.06.2014
comment
Я буду иметь в виду ваши предложения. Спасибо!!   -  person vran    schedule 18.06.2014


Ответы (2)


Перейдите к проекту mvc и добавьте пакет nuget Unity.Mvc3 или mvc4 в зависимости от вашего проекта. Это добавит в проект класс Bootstrapper.cs. Добавьте сюда свой тип, как показано ниже:

 public static class Bootstrapper
{
    public static void Initialise()
    {
        var container = BuildUnityContainer();
        DependencyResolver.SetResolver(new UnityDependencyResolver(container));
    }

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
        //Register the repository
        container.RegisterType<IProductRepository, SQLProductRepository>();
        return container;
    }
}

В global.config вызывается bootstrapper.initialise():

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();
        Bootstrapper.Initialise();

    }

Теперь вы можете настроить контроллеры следующим образом:

 public class HomeController : Controller
{
    private readonly IProductRepository productRepository;

    public HomeController(IProductRepository productRepository)
    {
        this.productRepository = productRepository;
    }

и правильный тип будет отправлен. Вы можете в любое время изменить реализацию в bootstrapper.cs без изменения кода.

person Avneesh    schedule 17.06.2014
comment
Круто, дайте мне знать, если возникнут проблемы, и я могу помочь - person Avneesh; 18.06.2014
comment
Единство — это только один пример. Изучите DI (внедрение зависимостей) и IoC (инверсия управления) для похожих фреймворков и выберите свой любимый. - person djikay; 18.06.2014
comment
Да, я исследовал различные способы достижения IOC, и я думаю, что Unity Resolver — хорошее решение. Я также столкнулся с такой же реализацией на веб-сайте asp.net (asp.net/web-api/overview/extensibility/) [ссылка]_italic_**жирный шрифт - person vran; 18.06.2014
comment
Я пытался использовать UnityDependencyResolver, но если я использую код, упомянутый @Avneesh, я получаю исключение. Мне нужно было изменить свой код, например, GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container) - person vran; 18.06.2014

Если вы можете определить, какой репозиторий следует использовать, на основе отправляемого HTTP-глагола, вы можете настроить свои маршруты на основе этого. Более подробную информацию об этом можно найти в этот вопрос.

person Dillie-O    schedule 17.06.2014
comment
Я так понимаю, что мой запрос WEB API будет устанавливать критерии? Должен ли я ожидать, что клиент, который когда-либо использует API, должен определить? Что, если мы хотим, чтобы это было абстрагировано от клиента, что происходит - Клиент просто связан с запросом, он не должен знать, что происходит, не так ли? - person vran; 18.06.2014
comment
Тогда более важный вопрос (на который я не нашел ответа в вашем исходном сообщении) заключается в том, что является определяющим условием между использованием репозиториев XML и SQL? - person Dillie-O; 18.06.2014