Единство и создание объектов - PullRequest
1 голос
/ 29 мая 2010

Я использую Unity в качестве контейнера IoC. Я пытаюсь реализовать тип IProviderRepository. Конкретная реализация имеет конструктор, который принимает тип IRepository. Когда я удаляю параметр конструктора из конкретной реализации, все работает нормально. Я уверен, что контейнер подключен правильно. Когда я пытаюсь создать конкретный объект с помощью конструктора, я получаю следующую ошибку:

"Текущая операция сборки (ключ сборки Ключ сборки [EMRGen.Infrastructure.Data.IRepository 1[EMRGen.Model.Provider.Provider], null]) failed: The current type, EMRGen.Infrastructure.Data.IRepository 1 [EMRGen.Model.Provider.Provider]] является интерфейсом и не может быть создан. Вам не хватает сопоставления типов? (Тип стратегии BuildPlanStrategy, index 3) ".

Можно ли достичь вышеупомянутой функциональности с Unity? А именно, Unity выводит конкретный тип из интерфейса, а также вводит в конструктор конкретного типа соответствующий конкретный объект на основе параметров конструктора. Ниже приведен пример моих типов, определенных в Unity, и список классов скелета для того, чего я хочу достичь. IProviderRepository реализован в ProviderRepository, который имеет конструктор, который ожидает тип IRepository.

 <typeAlias alias="ProviderRepositoryInterface" type="EMRGen.Model.Provider.IProviderRepository, EMRGen.Model" />
 <typeAlias alias="ProviderRepositoryConcrete" type="EMRGen.Infrastructure.Repositories.Providers.ProviderRepository, EMRGen.Infrastructure.Repositories" />
 <typeAlias alias="ProviderGenericRepositoryInterface" type="EMRGen.Infrastructure.Data.IRepository`1[[EMRGen.Model.Provider.IProvider, EMRGen.Model]], EMRGen.Infrastructure" />
 <typeAlias alias="ProviderGenericRepositoryConcrete" type="EMRGen.Infrastructure.Repositories.EntityFramework.ApplicationRepository`1[[EMRGen.Model.Provider.Provider, EMRGen.Model]], EMRGen.Infrastructure.Repositories" />
 <!-- Provider Mapping-->
 <typeAlias alias="ProviderInterface" type="EMRGen.Model.Provider.IProvider, EMRGen.Model" />
 <typeAlias alias="ProviderConcrete" type="EMRGen.Model.Provider.Doctor, EMRGen.Model" />

Проиллюстрируйте звонок, который делается внутри моего класса:

public class PrescriptionService
{
     PrescriptionService()
     {
         IUnityContainer uc = UnitySingleton.Instance.Container;
         UnityServiceLocator unityServiceLocator = new UnityServiceLocator(uc);
         ServiceLocator.SetLocatorProvider(() => unityServiceLocator);
         IProviderRepository pRepository =
             ServiceLocator.Current.GetInstance<IProviderRepository>();
     }
}

public class GenericRepository<IProvider> : IRepository<IProvider>
{
}

public class ProviderRepository :  IProviderRepository
{
    private IRepository<IProvider> _genericProviderRepository;

    //Explict public default constructor
    public ProviderRepository(IRepository<IProvider> genericProviderRepository) 
    {
        _genericProviderRepository = genericProviderRepository;
    }
}

1 Ответ

2 голосов
/ 29 мая 2010

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

Тем не менее, статический Сервисный Локатор является анти-паттерном . Попробуйте изменить код, чтобы вместо него использовать Constructor Injection . Это также значительно упростит ваш код:

public class PrescriptionService
{
    private readonly IProviderRepository pRepository;

    public PrescriptionService(IProviderRepository pRepository)
    {
        if (pRepository == null)
        {
            throw new ArgumentNullException("pRepository");
        }

        this.pRepository = pRepository;
    }
}

Используя Unity, вы сможете подключить его так:

var container = new UnityContainer();
container.RegisterType<PrescriptionService>();
container.RegisterType<IProviderRepository, ProviderRepository>();
container.RegisterType<IRepository<IProvider>, MyRepository<IProvider>>();

var ps = container.Resolve<PrescriptionService>();

Настройте контейнер и разрешите все компоненты в корне композиции приложения .

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

...