¿El enlace automático condicional de Ninject para cambiar el alcance (para el planificador de tareas) no funciona correctamente?
Dentro de la aplicación web MVC, el enlace DbContext funciona correctamente conInRequestScope()
kernel.Bind<DbContext>().ToSelf().InRequestScope();
kernel.Bind<IUnitOfWork<DbContext>>().To<UnitOfWork<DbContext>>();
Pero de unProgramador de tareas llamadaDbContext
enInRequestScope()
no se puede actualizar Db Table (sin ningún error), hasta que cambie Binding aInSingletonScope()
OInThreadScope()
Pregunta: Entonces, ¿hay alguna forma de cambiar el alcance deInSingletonScope()
/ InThreadScope()
para una llamada del programador de tareas.?
// PorProgramador de tareas Llama, intenté a continuación, pero no funciona correctamente
kernel.Bind<DbContext>().ToSelf()
.When(request => request.Target.Type.Namespace.StartsWith("NameSpace.ClassName"))
.InSingletonScope();
** Y probablemente extraño algo. Necesitas ayuda.
Fragmento de código actualizado
#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());
}
}
En Web.Config
<ScheduleTasks>
<Thread seconds="60">
<task name="ExecuteEmailTask" type="namespace.ExecuteEmailTask, AssemblyName" enabled="true" stopOnError="false" maxTries="5"/>
</Thread>
</ScheduleTasks>
En Global.asax
protected void Application_Start()
{
/* intialize Task */
TaskConfig.Init();
TaskManager.Instance.Initialize(TaskConfig.ScheduleTasks);
TaskManager.Instance.Start();
}
Sintaxis de enlace de Ninject
kernel.Bind<DbContext>().ToSelf().InRequestScope(); // Default bind
kernel.Bind<DbContext>().ToSelf()
.When(x => x.Parameters.OfType<NonRequestScopedParameter>().Any())
.InCallScope(); // For Scheduler
Nota: EmailTask
clase también tieneSomeReposity
como argumento de constructor.
Consultas: -
Pero, ¿cuál es la sintaxis de enlace para resolverTaskScheduler(IResolutionRoot resolutionRoot)
?¿Cuál es el código de configuración para ejecutar?TaskScheduler
?Como decir ponerIFakeDbContext
directamente en el constructor, ¿puede funcionar esto conIUnitOfWork<FakeDbContext>
?Problema
La tarea no se puede llamar con el constructor sobrecargado, solo se puede llamarTaskScheduler
Constructor predeterminado.
Pregunta 4: Puede cualquier forma de invocarTaskScheduler(IResolutionRoot resolutionRoot)
deTaskScheduler
Constructor predeterminado ?
Fragmento de código de muestra para crear tareas y ejecutar usandoSystem.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;
}
Pregunta 5: Puedo resolverTaskScheduler(IResolutionRoot resolutionRoot)
aquí ?
Resuelto
public ExecuteEmailTask() : this(DependencyResolver.Current.GetService<IResolutionRoot>())
O
public ExecuteEmailTask() : this(new Bootstrapper().Kernel) { }
public ExecuteEmailTask(IResolutionRoot resolutionRoot)
{
_resolutionRoot = resolutionRoot;
}