Services.Create
Services.Create(handlers, cachePolicy, cancelToken, entryPolicy) creates a service from a set of handlers.
// Create handler list
List<IHandlerBase> handlers = new List<IHandlerBase>();
// Add handlers
handlers.AddRange(new ServiceHandlers());
handlers.AddRange(new EmitHandlers());
// Create service
IService service = Services.Create(handlers, CachePolicies.Default);
Handlers can be provided in a tuple.
// Create service
IService service = Services.Create((new ServiceHandlers(), new EmitHandler()), CachePolicies.Default);
Services.CreateWithoutCache(handlers, cachePolicy, cancelToken, entryPolicy) creates a service without cache.
// Create service without cache
IService service = Services.CreateWithoutCache((new ServiceHandlers(), new EmitHandlers()));
Services.Create<Request, Response>() creates services to process only specific request and response types.
// Create service for specific type
IService<TypeRequest, Type> service = Services.Create<TypeRequest, Type>(new ServiceHandlers());
// Query
Type? type = service.Get(new TypeRequest("System.String"));
Note, many services use internal request types, and they require that service is generated as generic. Generic service can be casted type more constrained service type.
// Create generic service
IService service = Services.Create(new ServiceHandlers());
// Cast for specific request type
IService<TypeRequest, Type> typeService = service.Cast<TypeRequest, Type>();
// Query
Type? type = typeService.Get(new TypeRequest("System.String"));
ServiceBuilder
Alternative way to create service is to use ServiceBuilder.
// Create service
IService service = new ServiceBuilder()
.AddHandlers(new ServiceHandlers())
.Build();
EmptyServiceBuilder creates a completely uninitialized IServiceBuilder.
// Create service
IService service = new EmptyServiceBuilder()
.Defaults()
.AddHandlers(new ServiceHandlers())
.Build();
.AddHandler(object) and .AddHandler<T>() adds a handler source.
IService service = new ServiceBuilder()
.AddHandlers(new ServiceHandlers())
.Build();
.AddHandlers<List>() adds an enumerable of handlers.
IService service = new ServiceBuilder()
.AddHandlers<ServiceHandlers>()
.WithoutCache disables cache.
// Create service without cache
IService service = new ServiceBuilder()
.WithoutCache()
.Build<Request, Response>() type-casts the service to be constricted to process only specific request and response types.
// Create service for specific requests only
IService<TypeRequest, Type> service = new ServiceBuilder()
.AddHandlers(new ServiceHandlers())
.Build<TypeRequest, Type>();
Delegate Handlers
.AddHandler(Action<IQuery<Request, Response>>) adds a delegate as a handler.
// Create sum calculator
Action<IQuery<(int, int), int>> sumCalculator = q => q.Response.SetValue(q.Request.Item1 + q.Request.Item2);
// Create service
using var service = new ServiceBuilder()
.AddHandler(sumCalculator, order: 100)
.AddAvalancheServiceQueryLogger()
.Build();
// Issue request to sumHandler
int sum = service.GetRequired<(int, int), int>((5, 6));
Delegate Action<IQuery> handles every type of query. Second argument 'long? order' defines evaluation order.
// Create query logger
Action<IQuery> queryLogger =
q => WriteLine(Services.StatusCodes.GoodQueryCompleted.Template.Print(null, new object?[] { q.Request, q.Response.Value(), q.Response.Status }));
// Create service
using var service = new ServiceBuilder()
.AddHandler(sumCalculator, order: 100)
.AddHandler(queryLogger, order: long.MaxValue)
.AddAvalancheServiceQueryLogger()
.Build();
Async delegates are added as Func<IQuery<Request, Response>, Task>.
// Create async handler
Func<IQuery<string, string>, Task> urlDownloader =
async q =>
{
HttpResponseMessage msg = await new HttpClient().GetAsync(q.Request);
String content = await msg.Content.ReadAsStringAsync();
q.Response.SetValue(content);
};
// Create service
using var service = new ServiceBuilder()
.AddHandler(urlDownloader, order: 100)
.AddCachePolicy(CachePolicies.DontCache(typeof(string)))
.AddCachePolicy(CachePolicies.Default)
.Build();
// Get content
string? content = await service.GetAsync<string, string>("http://avalanche.fi");
// Print
Console.WriteLine(content);
And as Func<IQuery, Task> for async delegate.
// Create query logger async
Func<IQuery, Task> queryLogger =
async q => await Out.WriteLineAsync(Services.StatusCodes.GoodQueryCompleted.Template.Print(null, new object?[] { q.Request, q.Response.Value(), q.Response.Status }));
// Create service
using var service = new ServiceBuilder()
.AddHandler(sumCalculator, order: 100)
.AddHandler(queryLogger, order: long.MaxValue)
.AddCachePolicy(CachePolicies.Cache<string>())
.AddCachePolicy(CachePolicies.Default)
.Build();
Print tree
HandlerInfoProviderPrintExtensions.Print(IHandlerInfoProvider) prints handlers as a tree.
// Handlers
object handlers = ServiceHandlers.Instance;
// Adapt to IHandlerInfoProvider
IHandlerInfoProvider handlerSource = new HandlerInfoProvider(handlers);
// Print to tree
string tree = handlerSource.PrintTree();
// Print handlers
Console.WriteLine(tree);
Handlers are listed in evaluation order. Brackets contain evaluation order values [order1, order2, order3].
HandlerInfoProvider ├── [-9200000000000000000,3,0] ContextRequestHandler ├── [-9000000000000000000,0,1] RequestResolver ├── [-8999999999999000000,1,1] ContextParameterResolver ├── [0,4,0] TypeResolver ├── [0,5,0] NewRequestHandler ├── [0,7,2] SingletonHandler├── [0,8,2] SingletonHandler ├── [0,10,2] SingletonHandler ├── [0,11,2] SingletonHandler ├── [1000,6,0] AssemblyBuilderFactory ├── [1000,9,0] ModuleBuilderFactory ├── [10000,12,0] ServiceSelfProvider └── [9200000000000000000,2,0] BatchRequestHandler
Full Example
Full example
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Avalanche.Emit;
using Avalanche.Service;
using Avalanche.Utilities;
using Avalanche.Message;
using static System.Console;
public class service_construction
{
public static async Task Run()
{
{
// <01>
// Create handler list
List<IHandlerBase> handlers = new List<IHandlerBase>();
// Add handlers
handlers.AddRange(new ServiceHandlers());
handlers.AddRange(new EmitHandlers());
// Create service
IService service = Services.Create(handlers, CachePolicies.Default);
// </01>
Console.WriteLine(service);
}
{
// <02>
// Create service
IService service = Services.Create((new ServiceHandlers(), new EmitHandler()), CachePolicies.Default);
// </02>
}
{
// <03>
// Create service without cache
IService service = Services.CreateWithoutCache((new ServiceHandlers(), new EmitHandlers()));
// </03>
}
{
// <04>
// Create service for specific type
IService<TypeRequest, Type> service = Services.Create<TypeRequest, Type>(new ServiceHandlers());
// Query
Type? type = service.Get(new TypeRequest("System.String"));
// </04>
}
{
// <05>
// Create generic service
IService service = Services.Create(new ServiceHandlers());
// Cast for specific request type
IService<TypeRequest, Type> typeService = service.Cast<TypeRequest, Type>();
// Query
Type? type = typeService.Get(new TypeRequest("System.String"));
// </05>
}
{
// <10>
// Create service
IService service = new ServiceBuilder()
.AddHandlers(new ServiceHandlers())
.Build();
// </10>
}
{
// <10b>
// Create service
IService service = new EmptyServiceBuilder()
.Defaults()
.AddHandlers(new ServiceHandlers())
.Build();
// </10b>
}
{
// Create service
// <11>
IService service = new ServiceBuilder()
.AddHandlers(new ServiceHandlers())
.Build();
// </11>
}
{
// Create service
// <12>
IService service = new ServiceBuilder()
.AddHandlers<ServiceHandlers>()
// </12>
.Build();
}
{
// <13>
// Create service without cache
IService service = new ServiceBuilder()
.WithoutCache()
// </13>
.AddHandlers(ServiceHandlers.Instance)
.Build();
}
{
// <14>
// Create service for specific requests only
IService<TypeRequest, Type> service = new ServiceBuilder()
.AddHandlers(new ServiceHandlers())
.Build<TypeRequest, Type>();
// </14>
}
{
// <21>
// Handlers
object handlers = ServiceHandlers.Instance;
// Adapt to IHandlerInfoProvider
IHandlerInfoProvider handlerSource = new HandlerInfoProvider(handlers);
// Print to tree
string tree = handlerSource.PrintTree();
// Print handlers
Console.WriteLine(tree);
// </21>
}
// Delegate Handlers
{
// <31>
// Create sum calculator
Action<IQuery<(int, int), int>> sumCalculator = q => q.Response.SetValue(q.Request.Item1 + q.Request.Item2);
// Create service
using var service = new ServiceBuilder()
.AddHandler(sumCalculator, order: 100)
.AddAvalancheServiceQueryLogger()
.Build();
// Issue request to sumHandler
int sum = service.GetRequired<(int, int), int>((5, 6));
// </31>
}
{
// Create sum calculator
Action<IQuery<(int, int), int>> sumCalculator = q => q.Response.SetValue(q.Request.Item1 + q.Request.Item2);
// <32>
// Create query logger
Action<IQuery> queryLogger =
q => WriteLine(Services.StatusCodes.GoodQueryCompleted.Template.Print(null, new object?[] { q.Request, q.Response.Value(), q.Response.Status }));
// Create service
using var service = new ServiceBuilder()
.AddHandler(sumCalculator, order: 100)
.AddHandler(queryLogger, order: long.MaxValue)
.AddAvalancheServiceQueryLogger()
.Build();
// </32>
// Issue request to sumHandler
int sum = service.GetRequired<(int, int), int>((5, 6));
}
{
// <33>
// Create async handler
Func<IQuery<string, string>, Task> urlDownloader =
async q =>
{
HttpResponseMessage msg = await new HttpClient().GetAsync(q.Request);
String content = await msg.Content.ReadAsStringAsync();
q.Response.SetValue(content);
};
// Create service
using var service = new ServiceBuilder()
.AddHandler(urlDownloader, order: 100)
.AddCachePolicy(CachePolicies.DontCache(typeof(string)))
.AddCachePolicy(CachePolicies.Default)
.Build();
// Get content
string? content = await service.GetAsync<string, string>("http://avalanche.fi");
// Print
Console.WriteLine(content);
// </33>
}
{
// Create sum calculator
Action<IQuery<(int, int), int>> sumCalculator = q => q.Response.SetValue(q.Request.Item1 + q.Request.Item2);
// <34>
// Create query logger async
Func<IQuery, Task> queryLogger =
async q => await Out.WriteLineAsync(Services.StatusCodes.GoodQueryCompleted.Template.Print(null, new object?[] { q.Request, q.Response.Value(), q.Response.Status }));
// Create service
using var service = new ServiceBuilder()
.AddHandler(sumCalculator, order: 100)
.AddHandler(queryLogger, order: long.MaxValue)
.AddCachePolicy(CachePolicies.Cache<string>())
.AddCachePolicy(CachePolicies.Default)
.Build();
// </34>
// Issue request to sumHandler
int sum = service.GetRequired<(int, int), int>((5, 6));
}
}
}