Na początek wiem, że można to zrobić, ale ponieważ nie byłem zaangażowany w jego konfigurację ani wdrażanie, nie widziałem, jak to się stało.
W poprzedniej pracy, kiedy pomagałem w utrzymaniuaplikacja internetowa (MVC lub aplikacja internetowa), mieliśmy Twój zwykły wzorzec projektowy EF. Ale kiedy nadszedł czas, aby wykorzystać obiekty EF, wszystko, co musieliśmy zrobić, to zadeklarować właściwość na stronie / kontrolerze i mieliśmy dostęp do repozytorium / usługi.
Nie musieliśmy nic robić, aby zadeklarować jawność var prop1 = IOC.Resolve<Type>;
po deklaracji zostanie wypełniony automatycznie. Zakładałem, że to był zastrzyk zależności, ale nie widziałem żadnych napisów, jak to umożliwić.
Każda pomoc byłaby ogromna.
Edytuj 2014-04-13
Podjęto próbę wykonania iniekcji właściwości w pliku Global.asax w ten sposób
protected void Application_Start( object sender , EventArgs e ) {
App.Initialize( null );
if( HttpContext.Current != null ) {
var pg = base.Context.Handler as Page;
if( pg != null ) {
App.InjectProperties( pg );
}
}
}
Próbowałem zrobić if....
logika w Application_BeginRequest
bez powodzenia.
App.cs
public class App {
public static void Initialize( string log4netPath ) {
var container = new WindsorContainer();
container.Kernel.ComponentModelCreated += ( s => {
if( s.LifestyleType == LifestyleType.Undefined ) {
s.LifestyleType = LifestyleType.PerWebRequest;
}
} );
container.Install(
new DomainInstaller() ,
new RepositoryInstaller() ,
new ServiceInstaller()
);
container.Install( new SiteInstaller() );
if( log4netPath != null || string.IsNullOrWhiteSpace( log4netPath ) )
container.AddFacility( new LoggingFacility( LoggerImplementation.Log4net , log4netPath ) );
CWC.Init( container );
}
public static void InjectProperties( Page pg ) {
var type = pg.GetType();
foreach( var prop in type.GetProperties() ) {
if( CWC.IsInitialized ) {
try {
var obj = CWC.Resolve(prop.PropertyType);
prop.SetValue( pg , obj , null );
} catch( System.Exception ) {
//do nothing
}
}
}
}
}
DomainInstaller.cs (prawie wszystkie klasy Instalatora są skonfigurowane w ten sposób):
public class DomainInstaller : IWindsorInstaller {
#region IWindsorInstaller Members
public void Install( Castle.Windsor.IWindsorContainer container , Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store ) {
container.Register( Types.FromAssembly( Assembly.GetExecutingAssembly() )
.Where( t => t.Namespace.StartsWith( "Woodsoft.Domain" ) )
.WithService.FirstInterface().LifestylePerWebRequest()
);
}
#endregion
}
Więc myślę, że mogłem znaleźć mój problem, ale tak jestNie wiem, jak zaimplementować rozwiązanie, ponieważ zarówno moje strony, jak i MasterPages będą zawierać właściwości, które będą musiały zostać wstrzyknięte z mojej struktury danych EF. Poniżej znajduje się przykład implementacji MVC, ale obiekt Page i MasterPage nie mają bezpośredniego wspólnego interfejsu pochodnego, którego mogę używać tak jak w przypadku kontrolerów.
Kolejny projekt, wzorzec MVC:
public class SiteInstaller : IWindsorInstaller {
#region IWindsorInstaller Members
public void Install( IWindsorContainer container , IConfigurationStore store ) {
container.Register(
Classes.FromThisAssembly()
.BasedOn<IController>()
.LifestyleTransient()
);
}
#endregion
}
Czy jest jakaś pomoc w modyfikacji tego instalatora z MVC do formularzy internetowych? Z myślą o tym, że strony MasterPage i Page mają właściwości, które będą musiały zostać wstrzyknięte z kontenera Windsor.
Odpowiedzi:
0 dla odpowiedzi № 1- Zazwyczaj w MVC punkt wejścia jest akcją kontrolera, która renderuje widok.
- Domyślnie struktura MVC utworzy wystąpienie klasy kontrolera i wywoła odpowiednią akcję (metodę kontrolera)
- Po utworzeniu wystąpienia kontrolera MVC spróbuje wszystkiego, co w jego mocy, aby zapewnić wszystko, czego kontroler potrzebuje do jego utworzenia. na przykład
teraz rozważ ten kontroler MVC
public class MyController : Controller
{
public MyController()
{
// mvc can easily instantiate this controller
// since this is a parameter less controller.
}
}
teraz rozważ to:
public class MyController : Controller
{
public MyController(IRepository repository)
{
// mvc cannot easily instantiate this controller
// unless it knows how to inject a concrete implementation
// of the IRepository interface
}
}
zazwyczaj zespoły wykonują w ramach konfiguracji infrastruktury udostępnianie mechanizmu rozpoznawania zależności do struktury MVC.
na przykład
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
teraz dzieje się, gdy MVC chce utworzyć instancjękontroler potrzebuje konkretnego repozytorium IR, a także widzi, że może delegować odpowiedzialność na strukturę DI dostarczoną przez użytkownika. w tym przypadku Autofac.
zażąda od Autofaca podania typu IRepository.
a to, co zwykle robimy w Application Start, to
ContainerBuilder builder = new ContainerBuilder();
// critical line
builder.Register(c => new EFRepository()).As<IRepository>();
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
jak widać, kiedy kontroler zostanie utworzony, magicznie (no nie magicznie, wykonaliśmy trochę pracy u podstaw), pobierz typ IRepository i metodę akcji, która może zrobić:
var results = this.repository.GetEmployees();
podobnie do tego, jak IRepository jest wstrzykiwane przez konstruktor, można je również wstrzyknąć za pośrednictwem właściwości kontrolera.
builder.Register(c => new MyType()).As<IType>().PropertiesAutowired();
dla swojej strony, możesz też to zrobić
builder.RegisterType<YourPageType>().PropertiesAutowired();
DI (tutaj Autofac) automatycznie wypełni właściwość strony zarejestrowanym typem betonu.
itp.