依赖注入 – Ninject条件自绑定更改范围(For Task-scheduler)无法正常工作?
|
在MVC Web应用程序中,DbContext绑定与InRequestScope()正常工作 kernel.Bind<DbContext>().ToSelf().InRequestScope(); kernel.Bind<IUnitOfWork<DbContext>>().To<UnitOfWork<DbContext>>(); 但是从任务调度程序调用InRequestScope()中的DbContext无法更新Db表(没有任何错误),直到我将Binding更改为InSingletonScope()或InThreadScope() 问题:他们以任何方式将范围更改为InSingletonScope()/ InThreadScope()以进行任务计划程序调用. ? //对于任务计划程序调用,我尝试了bellow,但没有正常工作 kernel.Bind<DbContext>().ToSelf()
.When(request => request.Target.Type.Namespace.StartsWith("NameSpace.ClassName"))
.InSingletonScope();
**可能我想念一些东西.需要帮忙. 代码片段已更新 #region Commented Code
public EmailTask() : this
( DependencyResolver.Current.GetService<IMessageManager>(),DependencyResolver.Current.GetService<IUnitOfWork<DbContext>>()) { }
#endregion
public EmailTask(IMessageManager messageManager,IUnitOfWork<DbContext> unitOfWork)
{
this._messageManager = messageManager;
this._unitOfWork = unitOfWork;
ProcessEmail();
}
public class NonRequestScopedParameter : IParameter { ... }
public void ProcessEmail()
{
var temp = SomeRepository.GetAll();
SendEmail(temp);
temp.Date = DateTime.Now;
SomeRepository.Update(temp);
unitOfWork.Commit();
}
public class ExecuteEmailTask : ITask
{
private readonly IResolutionRoot _resolutionRoot;
private int _maxTries = 5;
public ExecuteEmailTask(IResolutionRoot resolutionRoot)
{
_resolutionRoot = resolutionRoot;
}
public void Execute(XmlNode node)
{
XmlAttribute attribute1 = node.Attributes["maxTries"];
if (attribute1 != null && !String.IsNullOrEmpty(attribute1.Value))
{
this._maxTries = int.Parse(attribute1.Value);
}
/// send email messages
var task = _resolutionRoot.Get<EmailTask>(new NonRequestScopedParameter());
}
}
在Web.Config中 <ScheduleTasks>
<Thread seconds="60">
<task name="ExecuteEmailTask" type="namespace.ExecuteEmailTask,AssemblyName" enabled="true" stopOnError="false" maxTries="5"/>
</Thread>
</ScheduleTasks>
在Global.asax中 protected void Application_Start()
{
/* intialize Task */
TaskConfig.Init();
TaskManager.Instance.Initialize(TaskConfig.ScheduleTasks);
TaskManager.Instance.Start();
}
Ninject绑定语法 kernel.Bind<DbContext>().ToSelf().InRequestScope(); // Default bind
kernel.Bind<DbContext>().ToSelf()
.When(x => x.Parameters.OfType<NonRequestScopedParameter>().Any())
.InCallScope(); // For Scheduler
注意:EmailTask类也有SomeReposity作为构造函数参数. 查询: – >但是解析TaskScheduler(IResolutionRoot resolutionRoot)的绑定语法是什么? 问题 Task无法使用重载构造函数调用,它只能调用TaskScheduler的默认构造函数. 问题4:可以以任何方式从TaskScheduler默认构造函数调用TaskScheduler(IResolutionRoot resolutionRoot)吗? 示例代码片段创建任务&使用System.Threading.Timer运行 private ITask createTask()
{
if (this.Enabled && (this._task == null))
{
if (this._taskType != null)
{
this._task = Activator.CreateInstance(this._taskType) as ITask;
}
this._enabled = this._task != null;
}
return this._task;
}
问题5:我可以在这里解决TaskScheduler(IResolutionRoot resolutionRoot)吗? 解决了 public ExecuteEmailTask(): 要么 public ExecuteEmailTask() : this(new Bootstrapper().Kernel) { }
public ExecuteEmailTask(IResolutionRoot resolutionRoot)
{
_resolutionRoot = resolutionRoot;
}
首先,你应该注意到InSingletonScope()对于DbContext的/ Sessions来说通常是一个坏主意.如果其他服务在此期间更改数据会发生什么?我建议调查一下这有什么影响.
对于您首次描述的场景,正确制定了.When(…)应该有效. 作为.When(…)绑定的替代方法,您还可以使用.Named(“FooBar”)绑定. ctor(Named["FooBar"] DbContext dbContext); 但请注意,这只是(容易)工作,以防您需要将DbContext注入单个构造函数.如果任务具有依赖性,并且这些依赖性也需要相同的DbContext实例,那么它会有点过时. 由于您更新了答案并说是这种情况,我建议采用完全不同的方法:使用请求参数作为When(…)条件与InCallScope绑定相结合的基础.请参阅下面的示例. 支持自己,这是代码:)实现需要ninject.extensions.NamedScope扩展(nuget). public class Test
{
// the two implementations are just for demonstration and easy verification purposes. You will only use one DbContext type.
public interface IFakeDbContext { }
public class RequestScopeDbContext : IFakeDbContext { }
public class CallScopeDbContext : IFakeDbContext { }
public class SomeTask
{
public IFakeDbContext FakeDbContext { get; set; }
public Dependency1 Dependency1 { get; set; }
public Dependency2 Dependency2 { get; set; }
public SomeTask(IFakeDbContext fakeDbContext,Dependency1 dependency1,Dependency2 dependency2)
{
FakeDbContext = fakeDbContext;
Dependency1 = dependency1;
Dependency2 = dependency2;
}
}
public class Dependency1
{
public IFakeDbContext FakeDbContext { get; set; }
public Dependency1(IFakeDbContext fakeDbContext)
{
FakeDbContext = fakeDbContext;
}
}
public class Dependency2
{
public IFakeDbContext FakeDbContext { get; set; }
public Dependency2(IFakeDbContext fakeDbContext)
{
FakeDbContext = fakeDbContext;
}
}
public class TaskScheduler
{
private readonly IResolutionRoot _resolutionRoot;
public TaskScheduler(IResolutionRoot resolutionRoot)
{
_resolutionRoot = resolutionRoot;
}
public SomeTask CreateScheduledTaskNow()
{
return _resolutionRoot.Get<SomeTask>(new NonRequestScopedParameter());
}
}
public class NonRequestScopedParameter : Ninject.Parameters.IParameter
{
public bool Equals(IParameter other)
{
if (other == null)
{
return false;
}
return other is NonRequestScopedParameter;
}
public object GetValue(IContext context,ITarget target)
{
throw new NotSupportedException("this parameter does not provide a value");
}
public string Name
{
get { return typeof(NonRequestScopedParameter).Name; }
}
// this is very important
public bool ShouldInherit
{
get { return true; }
}
}
[Fact]
public void FactMethodName()
{
var kernel = new StandardKernel();
// this is the default binding
kernel.Bind<IFakeDbContext>().To<RequestScopeDbContext>();
// this binding is _only_ used when the request contains a NonRequestScopedParameter
// in call scope means,that all objects built in the a single request get the same instance
kernel.Bind<IFakeDbContext>().To<CallScopeDbContext>()
.When(x => x.Parameters.OfType<NonRequestScopedParameter>().Any())
.InCallScope();
// let's try it out!
var task = kernel.Get<SomeTask>(new NonRequestScopedParameter());
// verify that the correct binding was used
task.FakeDbContext.Should().BeOfType<CallScopeDbContext>();
// verify that all children of the task get injected the same task instance
task.FakeDbContext.Should()
.Be(task.Dependency1.FakeDbContext)
.And.Be(task.Dependency2.FakeDbContext);
}
}
(编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
