ContextParameterAttribute
[ContextParameter(string name)] indicates that value in a field can be assigned from context dictionary during evaluation.
/// <summary>Request to add line to list</summary>
public record AddLineRequest([Request] object Line) : IRequestFor<List<string>>, IRequestNotToBeCached
{
/// <summary>List to modify.</summary>
[ContextParameter("List")]
public List<string> List { get; init; } = null!;
}
Handler
When handler receives the request, it should test whether value has been assigned to the field with [ContextParameter] attribute.
/// <summary>Add a line to list</summary>
public class AddLineHandler : IHandler<AddLineRequest, List<string>>
{
/// <summary>Add line to list</summary>
public void Handle(IQuery<AddLineRequest, List<string>> query)
{
// Already handled
if (query.Handled()) return;
// Get list
if (query.Request.List is not List<string> list) return;
// Get line
if (query.Request.Line is not string line) return;
// Add line
list.Add(line);
// Done
query.Response.SetValue(list);
}
}
Context-Assigned Request
ServiceHandlers must be included in the service stack for context parameter binding to work.
IService service = Services.Create((ServiceHandlers.Instance, new AddLineHandler()));
Request can be instantiated context-free.
// Create request to add line
IRequest addLineRequest = new AddLineRequest("Hello");
AddLineRequest └── Line = "Hello"
Contextual environment is carried in an IDictionary<string, object>.
// Create list
List<string> list = new List<string>();
// Create context
Dictionary<string, object> ctx = new() { { "List", list } };
Dictionary can be passed down in 'context' argument of IService methods.
// Invoke request and provide explicit context
service.TryInvoke(addLineRequest, context: ctx);
Context-Environment Request
ContextRequest and ContextRequest<T> are requests that evaluate a batch of subrequests in an environment where one context parameter is bound to a source of value that is to be evaluated.
// Request to evaluate in a context where "List" is bound to 'list'
ContextRequest contextRequest = new ContextRequest("List", list, addLineRequest);
ContextRequest<Object> ├── Key = "List" ├── Value = System.Collections.Generic.List`1[System.String] └── Requests[0] = AddLineRequest └── Line = "Hello"
Service is invoked without need for context dictionary.
// Invoke request
service.TryInvoke(contextRequest);
No Contextual Environment
If reference to 'list' is known at time of instantiation, it can be assigned directly into the request and no contextual environment is needed.
// Create request to add line to a list
IRequest addLineRequest2 = new AddLineRequest("Hello") { List = list };
// Invoke request
service.TryInvoke(addLineRequest2);
AddLineRequest ├── Line = "Hello" └── List = System.Collections.Generic.List`1[System.String]
Full Example
Full example
using System;
using System.Collections.Generic;
using Avalanche.Service;
public class request_contextparameter
{
public static void Run()
{
// Create service
// <01>
IService service = Services.Create((ServiceHandlers.Instance, new AddLineHandler()));
// </01>
// <02>
// Create request to add line
IRequest addLineRequest = new AddLineRequest("Hello");
// </02>
// <03>
// Create list
List<string> list = new List<string>();
// Create context
Dictionary<string, object> ctx = new() { { "List", list } };
// </03>
// <04>
// Invoke request and provide explicit context
service.TryInvoke(addLineRequest, context: ctx);
// </04>
// Print request
Console.WriteLine(addLineRequest.PrintTree());
// <11>
// Request to evaluate in a context where "List" is bound to 'list'
ContextRequest contextRequest = new ContextRequest("List", list, addLineRequest);
// </11>
// <12>
// Invoke request
service.TryInvoke(contextRequest);
// </12>
// Print request
Console.WriteLine(contextRequest.PrintTree());
// <13>
// Create request to add line to a list
IRequest addLineRequest2 = new AddLineRequest("Hello") { List = list };
// Invoke request
service.TryInvoke(addLineRequest2);
// </13>
// Print request
Console.WriteLine(addLineRequest2.PrintTree());
}
}
// <20>
/// <summary>Request to add line to list</summary>
public record AddLineRequest([Request] object Line) : IRequestFor<List<string>>, IRequestNotToBeCached
{
/// <summary>List to modify.</summary>
[ContextParameter("List")]
public List<string> List { get; init; } = null!;
}
// </20>
// <21>
/// <summary>Add a line to list</summary>
public class AddLineHandler : IHandler<AddLineRequest, List<string>>
{
/// <summary>Add line to list</summary>
public void Handle(IQuery<AddLineRequest, List<string>> query)
{
// Already handled
if (query.Handled()) return;
// Get list
if (query.Request.List is not List<string> list) return;
// Get line
if (query.Request.Line is not string line) return;
// Add line
list.Add(line);
// Done
query.Response.SetValue(list);
}
}
// </21>