Unity и OData (службы данных WCF) - PullRequest
1 голос
/ 22 июня 2011

Я пытаюсь использовать Unity с моей службой данных WCF (OData).У меня есть код, который выглядит следующим образом:

public class PatientService : DataService<IPatientRepository>

Я хочу, чтобы Unity вводил правильный объект для IPatientRepository во время выполнения (реальный PatientRepository или поддельный, который я использую для тестирования.)1005 * Я сделал:

IUnityContainer container = new UnityContainer();
container.RegisterType<IPatientRepository, MyEntities>();

Но когда я запускаю, я получаю:

Сервер обнаружил ошибку при обработке запроса.Сообщение об исключении: «Невозможно создать поставщика данных.Тип 'RepositoryInterfaces.IPatientRepository' для источника данных в 'PatientService.PatientService' является абстрактным. '

Есть ли способ внедрить эту зависимость?Или я должен поставить реальный класс в этом месте?

Ответы [ 2 ]

1 голос
/ 26 июля 2013

Класс ServiceLocator и шаблон ServiceLocator (анти) не должны использоваться здесь. Приведенный ниже код выглядит так, как будто это паттерн Service Locator (anti), но он не совсем.

Метод CreateDataSource - это самая ранняя точка в жизненном цикле запроса, которую я нашел для составления графа вашего объекта. Здесь он используется как корень композиции. Bootstrapper - это вспомогательный класс, который вызывает конфигурацию Unity, загружает ли она ее из XML или в коде.

public class  PatientService : DataService<IPatientRepository>
{
    public static void InitializeService(DataServiceConfiguration config)
    {
       // TODO: set rules to indicate which entity sets and service 
          operations are visible, updatable, etc.
          ...
    }

    [WebGet]
    public IQueryable<Patient> Patients()
    {
        return from p in CurrentDataSource.Patients select p;
    }

    protected override IPatientRepository CreateDataSource()
    {
        IUnityContainer container = new UnityContainer();
        Bootstrapper.Initialise(container);
        return container.Resolve<IPatientRepository>();
    }
}

Так что @Roy был прав, указав вам на метод CreateDataSource (). Однако следует избегать использования ServiceLocator как класса или шаблона. К сожалению, Microsoft почти заставила всех пойти по маршруту ServiceLocator с помощью таких классов, как ServiceLocator и DependencyResolver.

0 голосов
/ 23 июня 2011

Службы данных WCF не знают о вашем контейнере и, следовательно, не могут вызвать его, чтобы выяснить реализацию интерфейса, который вы передаете.

Аналогично, ваш контейнер может выполнять инъекцию конструктора, но не может динамически указывать T вDataService .

Итак, насколько я могу судить, невозможно использовать DataService с интерфейсом, а затем внедрить реализацию.

РЕДАКТИРОВАТЬ: Чтодолжно работать, как Vitek указал в комментариях, это просто объявить ваш класс DataSource с интерфейсом, а затем переопределить метод CreateDataSource ().В этом методе вы могли бы затем выполнить вызов ServiceLocator для реализации IYourInterface:

var myService = ServiceLocator.Get<IYourInterface>();

Это, конечно, требует, чтобы вы сконфигурировали свой контейнер для расположения службы.

Группа Patterns & Practicesочевидно, реализовал адаптер Unity для шаблона Service Locator, см. http://commonservicelocator.codeplex.com/wikipage?title=Unity%20Adapter&referringTitle=Home&ProjectName=commonservicelocator.

Подробнее о шаблоне Service Locator см. http://msdn.microsoft.com/en-us/library/ff648968.aspx.

...