ContextRegistry
有没有办法使用 Spring.NET 将依赖项注入到即时 CMS 控件中,理想情况下在初始化控件时不必使用?
2 回答
作为一名前 Immediacy 员工,我过去常常看到这类问题。
将即时性视为位于框架之上的标准 .net Web 应用程序。他们只是扩展了 Page 类之类的基类,并添加了一些全局有用的对象。
Immediacy 确实有自己的控件基类等,但没有什么能阻止您基于标准 .net 类创建自己的控件。
我见过的一个技巧是,您需要做一些可能会破坏即时功能的特定操作,即创建一个子应用程序,然后在您添加到主应用程序的自定义控件中从它调用页面。
这样,您的子应用程序可以在不破坏任何内容和父即时应用程序的情况下做自己喜欢的事情,并且只需从该应用程序读取流。
以最简单的形式,诀窍是简单地创建一个做一件事的控件......
WebClient wc = new WebClient();
this.Controls.Add(Page.ParseControl( wc.DownloadString("/childapp/yourcustomthing.aspx") ));
最干净的其他方法是将所需的子组件实现为我所看到的 ashx 处理程序。
唯一可能出现的问题是您失去了子应用程序中对象的即时框架,但您可以通过查询字符串轻松传递一些关键信息,然后构建自己的“依赖缓存”,其中包含您需要的内容。
我知道这不是一个理想的选择,但是当您需要做任何事情超出将列表/类似插件添加到页面或模板之外时,即时性确实有一种让生活变得困难的习惯。
我将用我在 Immediacy 6.x 中使用了一年多的解决方案来回答这个问题。理论上,这应该与 Alterian CMC 7.x(即时的继任者)一起使用,并进行一些修改。
这里的问题是 Immediacy 已经在 web.config 中定义了一个处理所有 aspx 页面的处理程序。但是,我发现这可以替换为PageHandlerFactory
web.config 中 Spring.NET 的条目,就像大多数 webforms 应用程序一样!
但是,仍然需要进行一些调整,因为开箱即用,预览器仍然存在问题。让 Spring.NET 与即时控件完美配合的过程是:
如文档中所述,将常用条目添加到 Spring.NET 的 web.config中。在这种情况下,我在 Spring.config 中有我的对象定义。
创建以下将处理所有依赖注入工作的抽象基类:
SpringImmedacyControl.cs
public abstract class SpringImmediacyControl : ImmediacyControl, ISupportsWebDependencyInjection { // You can do the same thing for other control classes, like LiteralControl #region ISupportsWebDependencyInjection Members public IApplicationContext DefaultApplicationContext { get; set; } #endregion protected override void OnInit(EventArgs e) { // Required for page preview, which is executed using Immediacy's page preview handler if (DefaultApplicationContext == null) { DefaultApplicationContext = ContextRegistry.GetContext() as WebApplicationContext; DefaultApplicationContext.ConfigureObject(this, this.GetType().FullName); } base.OnInit(e); } protected override void AddedControl(Control control, int index) { this.EnableViewState = false; // Handle DI for children ourselves - defaults to a call to InjectDependenciesRecursive if (DefaultApplicationContext != null) WebDependencyInjectionUtils.InjectDependenciesRecursive(DefaultApplicationContext, control); base.AddedControl(control, index); } }
这类似于Spring.NET 文档上的服务器端控件代码。但是,需要额外的
OnInit
& 空检查代码是因为预览器在 Immediacy 自己的预览器 HTTP 处理程序下呈现控件。这意味着需要手动调用 Spring.NET 的上下文注册表来注入依赖项。对于您希望与 Spring.NET 的控制反转容器一起使用的任何控件,请将相关条目添加到 Spring.config,例如:
示例控件.cs
public class SampleControl : SpringImmediacyControl, INamingContainer { public string Text { get; set; } protected string InjectedText { get; set; } public SampleControl() : base() { Text = "Hello world"; } protected override void RenderContents(HtmlTextWriter output) { output.Write(string.Format("{0} {1}", Text, InjectedText)); } }
Spring.config
<objects xmlns="http://www.springframework.net"> <object type="MyProject.SampleControl, MyAssembly" abstract="true"> <property name="InjectedText" value="from Spring.NET" /> </object> </objects>
如果一切都正确完成,您将拥有写出“来自 Spring.NET 的 Hello world!”的控件。在页面中使用时。
顺便说一句,如果您希望创建与 Spring.NET 兼容的子类,则该过程类似ButtonPluginConfig
,除了这些子类始终在 Immediacy 自己的 HTTP 处理程序下执行以进行控制配置,因此始终需要调用 Spring.NET 的上下文注册表。我还包含了一个派生自ButtonPluginConfig
上述要点的抽象类。