EDIT: I misread tym i myślałem, że to pytanie o sposób korzystania autofac zarejestrować zależności. Jeśli chcesz zachować ten sam UnitOfWork, musisz zmienić czas życia instancji na coś. Jeśli używasz tego w aplikacji ASP.NET lub WCF można zarejestrować zależności tak:
typeBuilder.RegisterType<UnitOfWork>().InstancePerLifetimeScope();
typeBuilder.RegisterType<Repository>();
typeBuilder.RegisterType<Service>();
Pierwszą rzeczą, którą trzeba zrobić, aby wykorzystać pojemnik jak Autofac to zarejestrować wszystkie swoje zależności. W Autofac możesz to zrobić na kilka sposobów, ale wszystkie z nich polegają na użyciu ContainerBuilder
. Numer ContainerBuilder
opiera się na metodach rozszerzania, dlatego upewnij się, że masz instrukcję using
dla przestrzeni nazw Autofac.
można jednoznacznie określić metody fabryczne:
// Explicitly
var builder = new ContainerBuilder();
builder.Register<UnitOfWork>(b => new UnitOfWork());
builder.Register<Repository>(b => new Repository(b.Resolve<UnitOfWork>()));
builder.Register(b => new Service(b.Resolve<Repository>(), b.Resolve<UnitOfWork>()));
Korzystanie ContainerBuilder mamy dostęp metodę Register<>()
dostarczenie interfejsu serwisowego (co jest, jak będziemy się pytać pojemnik za usługę) w tym przypadku , Nie używam interfejsów, tylko właściwy typ. Za każdym razem, gdy poprosisz kontener o numer UnitOfWork
, użyje on metody fabrycznej new UnitOfWork()
do wygenerowania. W prawdziwym życiu prawdopodobnie prosiłbyś o IUnitOfWork
. Może to być trochę gadatliwe, ale jest bardzo przydatne, gdy potrzebujesz niestandardowej logiki do tworzenia zależności.
Można używać budowniczych jak każdego innego kontenera zależności i po prostu zarejestrować typy.
// Implicitly
var typeBuilder = new ContainerBuilder();
typeBuilder.RegisterType<UnitOfWork>();
typeBuilder.RegisterType<Repository>();
typeBuilder.RegisterType<Service>();
Podejście to opiera się na rejestracji wszystkie zależności potrzebne do zbudowania klasy. Kontener użyje refleksji do rozwiązania wszelkich argumentów konstruktora. Jeśli argument nie zostanie zarejestrowany, kontener wygeneruje wyjątek z typem, którego nie może rozwiązać. W tym przypadku usługa jest zależna od UnitOfWork
i Repository
. Repository
ma również zależność od UnitOfWork
. Te zależności są wyrażone jako argumenty konstruktora. Aby zażądać od kontenera Repository
lub Service
, muszą zostać zarejestrowane wszystkie zależności:
Można zastosować podejście konfiguracyjne.
Jeśli używasz pliku app.config, można określić plik konfiguracyjny tak:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration"/>
</configSections>
<autofac defaultAssembly="AutoFacTest">
<components>
<component
type="AutoFacTest.Repository, AutoFacTest"
service="AutoFacTest.Repository" />
<component
type="AutoFacTest.UnitOfWork, AutoFacTest"
service="AutoFacTest.UnitOfWork" />
<component
type="AutoFacTest.Service, AutoFacTest"
service="AutoFacTest.Service" />
</components>
</autofac>
</configuration>
pierwsze należy zauważyć, że mamy do definiowania sekcji config (zauważyć <ConfigSections>
). Następnie możemy utworzyć sekcję <autofac>
, która definiuje wszystkie nasze zależności. Notacja jest dość prosta, w zasadzie dla każdego zależności tworzony jest <component>
.Każdy komponent ma atrybut service
, który definiuje typ, który będzie żądany. Istnieje również atrybut type
, który definiuje obiekt, który ma zostać utworzony, gdy żądana jest instancja usługi. Jest to analogiczne do builder.Register<UnitOfWork>(b => new UnitOfWork())
, gdzie UnitOfWork
jest żądaną usługą (iw tym przypadku) również typem, który ma zostać utworzony.
Aby utworzyć konstruktor za pomocą konfiguracji, użyj ConfigurationSettingsReader()
// Config
var configBuilder = new ContainerBuilder();
configBuilder.RegisterModule(new ConfigurationSettingsReader("autofac"));
trzeba przejść w imię swojej sekcji konfiguracji (w tym przypadku autofac
). Po skonfigurowaniu zależności należy zbudować kontener. ContainerBuilder
zawiera metodę, aby to zrobić:
var container = builder.Build();
var typeContainer = typeBuilder.Build();
var configContainer = configBuilder.Build();
A skoro masz pojemnik, można zażądać wystąpień usługi:
container.Resolve<Service>().DoAwesomeness();
typeContainer.Resolve<Service>().DoAwesomeness();
configContainer.Resolve<Service>().DoAwesomeness();
kompletny program:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autofac;
using Autofac.Configuration;
namespace AutoFacTest
{
class Program
{
static void Main(string[] args)
{
// Explicitly
var builder = new ContainerBuilder();
builder.Register<UnitOfWork>(b => new UnitOfWork());
builder.Register<Repository>(b => new Repository(b.Resolve<UnitOfWork>()));
builder.Register(b => new Service(b.Resolve<Repository>(), b.Resolve<UnitOfWork>()));
// Implicitly
var typeBuilder = new ContainerBuilder();
typeBuilder.RegisterType<UnitOfWork>();
typeBuilder.RegisterType<Repository>();
typeBuilder.RegisterType<Service>();
// Config
var configBuilder = new ContainerBuilder();
configBuilder.RegisterModule(new ConfigurationSettingsReader("autofac"));
var container = builder.Build();
var typeContainer = typeBuilder.Build();
var configContainer = configBuilder.Build();
container.Resolve<Service>().DoAwesomeness();
typeContainer.Resolve<Service>().DoAwesomeness();
configContainer.Resolve<Service>().DoAwesomeness();
Console.Read();
}
}
public class Repository
{
private readonly UnitOfWork _unitOfWork;
public Repository(UnitOfWork uow)
{
_unitOfWork = uow;
}
public void PrintStuff(string text)
{
Console.WriteLine(text);
}
}
public class Service
{
private readonly Repository _repository;
private readonly UnitOfWork _unitOfWork;
public Service(Repository repo, UnitOfWork uow)
{
_repository = repo;
_unitOfWork = uow;
}
public void DoAwesomeness()
{
_repository.PrintStuff("Did awesome stuff!");
_unitOfWork.Commit();
}
}
public class UnitOfWork
{
public bool Commit()
{
return true;
}
}
}
I przepraszam, mój angielski jest słaby – DotDot