2015-05-11 4 views
0

Позволяет сказать, что я вручную экземпляр мои объекты, как это:Управление экземплярами Autofac?

var context = new MyDbContext(); 
_uow = new UnitOfWork(context); 
_repository = new Repository<Account>(context, _uow); 

Вместо этого я хочу, чтобы ввести их и зарегистрировать их как так:

private readonly IUnitOfWorkAsync _uow; 
private readonly IRepositoryAsync<Account> _repository; 

public AccountService(IUnitOfWorkAsync uow, IRepositoryAsync<Account> repository) 
{ 
    _uow = uow; 
    _repository = repository; 
} 

Вот регистрация.

builder.RegisterType<MyDbContext>().As<IDataContextAsync>().InstancePerDependency(); 
builder.RegisterType<UnitOfWork>().As<IUnitOfWorkAsync>(); 
builder.RegisterGeneric(typeof (Repository<>)).As(typeof (IRepositoryAsync<>)); 
builder.RegisterAssemblyTypes(typeof(AccountService).Assembly) 
    .Where(t => t.Name.EndsWith("Service")) 
    .As(t => t.GetInterfaces().FirstOrDefault(
     i => i.Name == "I" + t.Name)); 

Мое обслуживание публикуется в IIS и выглядит нормально, но работает неправильно. Например, я иду, чтобы вставить новую учетную запись, и она не сохраняется в БД и не является ошибкой. Кажется, что введенный UnitOfWork не тот же UnitOfWork, который использовался для создания экземпляра репозитория. Я подтвердил это с какой-то код в конструктора, как так:

if(_uow.GetHashCode() != _repository.MyUow.GetHashCode()) 
    throw new ArgumentException("Bad UOW"); 

Если я впрыснуть UnitOfWork и хранилище I Г.Е. исключение. Если я вручную создаю экземпляр объектов, я НЕ получаю исключение. Я попытался изменить свою регистрацию на .InstancePerOwned() для службы и другие различные регистрационные изменения безрезультатно. Как я могу использовать регистрацию Autofac для надлежащего создания экземпляра моего репозитория НА ОСНОВЕ ЕДИНИЦЫ, которые он уже создал? Я думал, что значение по умолчанию .InstancePerDependency() было бы достаточно, но не было бы. Благодарю.


Edit 1: Я использую WCF и вот мой CustomHostFactory. Я не вижу возможности указать .InstancePerRequest(), как указано в документации. Кроме того, интересно, что эта строка не имеет значения в приведенном ниже коде. Все работает точно так же, если я просто возьму его. AutofacServiceHostFactory.Container = контейнер;

protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
{ 
    Type contractType = GetContractType(serviceType); 

    var builder = new ContainerBuilder(); 
    builder.RegisterType<MyDbContext>().As<IDataContextAsync>(); 
    builder.RegisterType<UnitOfWork>().As<IUnitOfWorkAsync>(); 

    builder.RegisterGeneric(typeof (Repository<>)).As(typeof (IRepositoryAsync<>)); 

    builder.RegisterAssemblyTypes(typeof(AccountService).Assembly) 
     .Where(t => t.Name.EndsWith("Service")) 
     .As(t => t.GetInterfaces().FirstOrDefault(
      i => i.Name == "I" + t.Name)); 

    var container = builder.Build(); 
    AutofacServiceHostFactory.Container = container; 
    var host = new CustomServiceHost(serviceType, baseAddresses); 
    host.AddDependencyInjectionBehavior(contractType, container); 

    return host; 
} 
private static Type GetContractType(Type serviceType) 
{ 
    return serviceType.GetInterfaces() 
     .FirstOrDefault(i => Attribute.IsDefined(i, typeof(ServiceContractAttribute), false)); 
} 
+0

Если вы зарегистрируйте их как «InstancePerRequest», он должен работать.Какое приложение вы строите? Услуги WCF? Если да, то вы настроили Autofac для работы с WCF? http://autofac.readthedocs.org/ru/latest/integration/wcf.html –

+0

Да, это WCF. Я обновил сообщение, чтобы показать метод CreateServiceHost CustomServiceHostFactory. Я не вижу возможности установить регистрацию как InstancePerRequest. – BBauer42

+0

Для настройки 'Autofac' и' WCF 'необходимо выполнить 2 шага. Сначала вам нужно установить контейнер и изменить способ «Autofac», который знает вашу услугу (путем изменения вашего файла svc или добавления конфигурации WCF и т. Д. См. Документацию для вашего конкретного случая) –

ответ

0

мне нужно изменить регистрацию, как так:

var builder = new ContainerBuilder(); 
builder.RegisterType<MyDbContext>().As<IDataContextAsync>().InstancePerLifetimeScope(); 
builder.RegisterType<UnitOfWork>().As<IUnitOfWorkAsync>().InstancePerLifetimeScope(); 
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepositoryAsync<>)).InstancePerLifetimeScope(); 

builder.RegisterAssemblyTypes(typeof(AccountService).Assembly) 
    .Where(t => t.Name.EndsWith("Service")) 
    .As(t => t.GetInterfaces().FirstOrDefault(
     i => i.Name == "I" + t.Name)).InstancePerLifetimeScope(); 

AutofacHostFactory.Container = builder.Build(); 

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

InstanceContextMode = InstanceContextMode.PerCall 
0

InstancePerRequest доступен только для пакетов интеграции WebForms и MVC.

Попытайтесь использовать Autofac-интеграцию с WCF в режиме svc.less, как описано ниже.

From Autofac docs:

Svc-Less Услуги

Если вы хотите воспользоваться услугами без SVC-файла, Autofac будет работать с этим.

Как показано выше, зарегистрируйте свою службу в контейнере.

var builder = new ContainerBuilder(); 
builder.RegisterType<Service1>(); 
AutofacHostFactory.Container = builder.Build(); 

Для использования SVC-менее услуг, добавить запись фабрики под элементом serviceActivation в файле web.config. Это гарантирует, что AutofacServiceHostFactory используется для активации службы.

<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"> 
    <serviceActivations> 
    <add factory="Autofac.Integration.Wcf.AutofacServiceHostFactory" 
     relativeAddress="~/Service1.svc" 
     service="TestService.Service1" /> 
    </serviceActivations> 
</serviceHostingEnvironment> 
+0

Я прочитал документацию. Во-первых, где в WCF происходит ли «регистрация вашего сервиса с контейнером»? Во-вторых, я хочу использовать CustomServiceHostFactory: AutofacServiceHostFactory. Я не вижу такого примера (документы или в Интернете). Возможно ли это? В-третьих, я считаю, что проблема более специфична для регистрации, т. Е. С использованием того же UoW в репозитории, что контейнер создает экземпляр для первого параметра, введенного в конструктор AccountService. Прошу прощения за «неправильную» попытку использования Autofac, но ваша срыгивающаяся документация выше не помогает мне «правильно» использовать ее. – BBauer42

+0

Ну, я не совсем уверен, что это имеет отношение к вашей фабрике. Вам нужно приблизиться к вашим регистрациям. Вы регистрируете свой UoW в зависимости от области зависимости. Вы не делаете этого явно, но это область по умолчанию. У вашего сервиса есть зависимость от UoW, и ваш репозиторий имеет зависимость от UoW. Они получают две разные версии, ваш UoW инициализируется дважды. Как уже упоминалось, у вас есть расширение InstancePerRequest для интеграции MVC, но это не более чем настраиваемый жизненный цикл, который создается и размещается вместе с HTTP-запросом. –