0

首先,我知道这是可以做到的,但由于我没有参与设置或实施它,所以我没有看到它是如何完成的。

在以前的工作中,当我帮助支持 Web 应用程序(MVC 或 Web-App)时,我们有你常用的 EF 设计模式。但是当需要使用 EF 对象时,我们所要做的就是在 Page/Controller 中声明一个属性,然后我们就可以访问 Repository/Service。

只要在声明var prop1 = IOC.Resolve<Type>;后明确声明,我们就不必做任何事情,它将自动填充。我认为这是依赖注入,但没有看到任何关于如何使这成为可能的文章。

任何帮助都会非常有用。

编辑 2014-04-13

尝试像这样在 Global.asax 文件中进行属性注入

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 );
        }
    }
}

我试过做if....逻辑,但都Application_BeginRequest没有成功。

应用程序.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(几乎所有的安装程序类都是这样设置的):

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
}

所以我想我可能已经找到了我的问题,但我不确定如何实施解决方案,因为我的 Pages 和 MasterPages 都将包含需要从我的 EF 数据框架注入的属性。下面是一个 MVC 实现的示例,但是 Page 和 MasterPage 对象没有我可以像控制器一样使用的直接公共派生接口。

另一个项目,MVC 模式:

public class SiteInstaller : IWindsorInstaller {
    #region IWindsorInstaller Members

    public void Install( IWindsorContainer container , IConfigurationStore store ) {
        container.Register(
            Classes.FromThisAssembly()
                .BasedOn<IController>()
                    .LifestyleTransient()
        );
    }

    #endregion
}

将此安装程序从 MVC 修改为 WebForms 有什么帮助吗?MasterPage 和 Page 都具有需要从 Windsor Container 注入的属性的意图。

4

1 回答 1

0
  • 通常在 MVC 中,入口点是呈现视图的控制器操作。
  • 默认情况下,MVC 框架将实例化一个控制器类并调用适当的操作(控制器方法)
  • 当控制器被实例化时,MVC 将尽其所能提供控制器实例化它所需的一切。例如

现在考虑这个 MVC 控制器

public class MyController : Controller
{
 public MyController()
 {
  // mvc can easily instantiate this controller 
  // since this is a parameter less controller.
 }
}

现在考虑一下:

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
 }
}

通常,团队作为基础设施设置的一部分所做的是为 MVC 框架提供依赖关系解析器。

例如

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

现在发生的情况是,当 MVC 想要实例化控制器时,它需要一个具体的 IRepository 并且还看到它可以将责任委托给用户提供的 DI 框架。在这种情况下,Autofac。

它会要求 Autofac 提供一个 IRepository 类型。

我们通常在 Application Start 中做的是

ContainerBuilder builder = new ContainerBuilder();

// critical line
builder.Register(c => new EFRepository()).As<IRepository>();

IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

如您所见,当控制器被实例化时,它会神奇地(不是神奇地,我们做了一些基础工作)获得 IRepository 类型,并且 action 方法可以执行以下操作:

var results = this.repository.GetEmployees();

类似于通过构造函数注入 IRepository 的方式,您也可以通过控制器的属性注入它。

builder.Register(c => new MyType()).As<IType>().PropertiesAutowired();

对于你的页面,你也可以做

builder.RegisterType<YourPageType>().PropertiesAutowired();

DI(此处为 Autofac)将使用注册的具体类型自动填充页面属性。

等等

于 2014-04-13T00:52:23.873 回答