我在使用spring.net 4.0开发Web应用程序方面有一定的经验,nhibernate 3.0用于基于ASP.net的Web应用程序。最近我遇到了一种情况,我需要使用spring.net来注入属于WorkerRole
类的服务依赖项。我正常创建了app.config文件,正如我通常使用的spring.config文件一样。这是为了清楚起见。 (我已经排除了根节点)
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web" requirePermission="false" />
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" requirePermission="false" />
<section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" />
</sectionGroup>
</configSections>
<spring>
<context>
<!-- Application services and data access that has been previously developed and tested-->
<resource uri="assembly://DataAccess/data-access-config.xml" />
<resource uri="assembly://Services/service-config.xml" />
<resource uri="AOP.xml" />
<resource uri="DI.xml"/>
</context>
<parsers>
<parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
<parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" />
<parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
</parsers>
</spring>
同样,这是AOP.xml
<object id="FilterServiceProxy" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
<property name="proxyInterfaces" value="Domain.IFilterService"/>
<property name="target" ref="FilterService"/>
<property name="interceptorNames">
<list>
<value>UnhandledExceptionThrowsAdvice</value>
<value>PerformanceLoggingAroundAdvice</value>
</list>
</property>
</object>
</objects>
和DI.xml
<object type="FilterMt.WorkerRole, FilterMt" >
<property name="FilterMtService1" ref="FilterServiceProxy"/>
</object>
但是,我无法将任何依赖项注入worker角色。有人可以让我知道我在做错了吗?是否有不同的方法为Windows Azure应用程序配置Spring.net DI?
我没有得到任何配置错误,但我发现没有注入依赖项,因为我尝试注入的属性对象仍为空。
答案 0 :(得分:10)
根据我的经验,您不能向WorkerRole类(实现RoleEntryPoint的类)注入任何内容。到目前为止,我使用Unity(我还为Unity构建了自己的助手来帮助我注入Azure设置),我有自己的基础架构运行并由Unity构建,但是我在工作者角色的代码。
例如,我在RoleEntry点的OnStart()方法中初始化依赖项容器,在那里我解决了我需要的任何东西。然后在我的Run()方法中,我在已解析的依赖项上调用一个方法。
以下是我的RoleEntryPoint实施的快速剥离版本:
public class WorkerRole : RoleEntryPoint
{
private UnityServiceHost _serviceHost;
private UnityContainer _container;
public override void Run()
{
// This is a sample worker implementation. Replace with your logic.
Trace.WriteLine("FIB.Worker entry point called", "Information");
using (this._container = new UnityContainer())
{
this._container.LoadConfiguration();
IWorker someWorker = this._container.Resolve<IWorker>();
someWorker.Start();
IWorker otherWorker = this._container.Resolve<IWorker>("otherWorker");
otherWorker.Start();
while (true)
{
// sleep 30 minutes. we don't really need to do anything here.
Thread.Sleep(1800000);
Trace.WriteLine("Working", "Information");
}
}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
this.CreateServiceHost();
return base.OnStart();
}
public override void OnStop()
{
this._serviceHost.Close(TimeSpan.FromSeconds(30));
base.OnStop();
}
private void CreateServiceHost()
{
this._serviceHost = new UnityServiceHost(typeof(MyService));
var binding = new NetTcpBinding(SecurityMode.None);
RoleInstanceEndpoint externalEndPoint =
RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["ServiceEndpoint"];
string endpoint = String.Format(
"net.tcp://{0}/MyService", externalEndPoint.IPEndpoint);
this._serviceHost.AddServiceEndpoint(typeof(IMyService), binding, endpoint);
this._serviceHost.Open();
}
正如您所看到的,我自己的逻辑是IWorker接口,我可以拥有尽可能多的实现,并且我在Run()方法中对它们进行了充实。我做的更多是拥有一个WCF服务,再次通过DI与Unity完全配置。这是我的IWorker界面:
public interface IWorker : IDisposable
{
void Start();
void Stop();
void DoWork();
}
就是这样。我的WorkerRole中没有任何“硬”依赖项,只有Unity容器。我的两个工作人员的DI非常复杂,一切都很顺利。
您无法直接干扰WorkerRole.cs类的原因是它由Windows Azure基础架构实例化,而不是由您自己的基础架构实例化。您必须接受这一点,并在WorkerRole适当的方法中构建您的基础结构。并且不要忘记你必须永远不要退出/中断/返回/退出Run()方法。这样做会标记Windows Azure基础结构,使您的代码出现问题并触发角色回收。
希望这有帮助。
答案 1 :(得分:0)
我知道这是一个老问题,但我正在经历相同的学习曲线,并希望与那些努力理解力学的人分享我的发现。
您无法在工作者角色类中访问DI的原因是因为它在IIS之外的操作系统中的单独进程中运行。将您的WebRole
类视为在Windows服务中运行。
我已经对我的MVC网站和WebRole课程进行了一些实验:
public class WebRole : RoleEntryPoint
{
public override void Run()
{
while (true)
{
Thread.Sleep(10000);
WriteToLogFile("Web Role Run: run, Forest, RUN!");
}
}
private static void WriteToLogFile(string text)
{
var file = new System.IO.StreamWriter("D:\\tmp\\webRole.txt", true); // might want to change the filename
var message = string.Format("{0} | {1}", DateTime.UtcNow, text);
file.WriteLine(message);
file.Close();
}
}
这会每隔10秒(或左右)向文件写一个新字符串。现在以调试模式启动Azure站点,确保将站点部署到Azure模拟器并启动VS中的调试器。检查站点是否正在运行,并检查WebRole是否正在写入相关文件。
现在,在不停止VS调试器的情况下,停止IIS Express(如果在完全安装中运行它,则为IIS)。您网站中的所有操作现在都已停止。但是,如果您检查临时文件,则该过程仍在运行,并且您仍然每10秒钟添加一行新行。直到你停止调试器。
因此,无论您在Web应用程序的内存中加载了什么,都在IIS内部,而在Worker Role中不可用。您需要从头开始重新配置您的DI和其他服务。
希望这可以帮助别人更好地理解基础知识。