/ / Jak automatycznie ładować obiekty do właściwości strony - C #, asp.net, Entity-Framework, dependency-injection, property-injection

Jak automatycznie ładować obiekty do właściwości strony - c #, asp.net, framework-encja, wstrzykiwanie zależności, wstrzykiwanie właściwości

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.