Services.Create
Services.Create(handlers, cachePolicy?, cancelToken?, entryPolicy?) creates a service from a set of handlers.
IService service = Services.Create(ServiceHandlers.Instance, CachePolicies.Default);
CachePolicies.Default is used if cachePolicy argument is not provided.
IService service = Services.Create(ServiceHandlers.Instance);
IEnumerable is enumerated for handlers.
// Create handler list
List<object> handlers = new List<object>();
// Add handlers
handlers.AddRange(ServiceHandlers.Instance);
handlers.Add(Avalanche.Emit.Module.Instance);
// Create service
IService service = Services.Create(handlers);
Handlers can be provided in a tuple (a, b, c, ...).
IService service = Services.Create(Avalanche.Emit.Module.Instance);
Services.CreateWithoutCache(handlers, cancelToken?, entryPolicy?) creates a service without cache.
IService service = Services.CreateWithoutCache(Avalanche.Emit.Module.Instance);
Services.Create<Request, Response>() creates a service for specific Request and Response types.
// Create service for specific type
IService<TypeRequest, Type> service = Services.Create<TypeRequest, Type>(ServiceHandlers.Instance);
// Query
Type? type = service.Get("System.String");
IHandlerBase can be added to handler source.
// Create handler
IHandlerBase logger = new MyHandler();
// Create service for specific type
IService service = Services.Create((ServiceHandlers.Instance, logger));
// Query
Type? type = service.Get<TypeRequest, Type>("System.String");
Delegate is adapted to handler.
// Create handler as delegate
Action<IQuery> logger = q => Console.WriteLine(q.Request);
// Create service for specific type
IService service = Services.Create((ServiceHandlers.Instance, logger));
// Query
Type? type = service.Get<TypeRequest, Type>("System.String");
DependencyInjection ServiceDescriptor is adapted to handler.
// Create service descriptor
ServiceDescriptor listService = ServiceDescriptor.Transient(typeof(IList<>), typeof(List<>));
// Create service for specific type
IService service = Services.Create((ServiceHandlers.Instance, listService));
// Query for a new transient list
IList<int> ints = service.GetRequired<ServiceRequest<IList<int>>, IList<int>>(default);
ServiceBuilder
Alternative way to create service is to use ServiceBuilder. Builder is initialized with default entry and cache policy.
IService service = new ServiceBuilder()
.AddHandlers(ServiceHandlers.Instance)
.Build();
ServiceBuilderBase is uninitialized IServiceBuilder without default policies.
IService service = new ServiceBuilderBase()
.Defaults()
.AddHandlers(ServiceHandlers.Instance)
.Build();
.AddHandler(object) and .AddHandler<T>() adds a handler or handler source.
IService service = new ServiceBuilder()
.AddHandlers(ServiceHandlers.Instance)
.Build();
.AddHandlers<List>() adds an enumerable of handlers.
IService service = new ServiceBuilder()
.AddHandlers<ServiceHandlers>()
.WithoutCache disables cache.
IService service = new ServiceBuilder()
.WithoutCache()
.Build<Request, Response>() type-casts the service to be constricted to process only specific request and response types.
IService<TypeRequest, Type> service = new ServiceBuilder()
.AddHandlers(ServiceHandlers.Instance)
.Build<TypeRequest, Type>();
.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.MessageDescription.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.MessageDescription.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
.Print(IHandlerInfoProvider) prints handlers as a tree.
// Adapt to IHandlerInfoProvider
IHandlerInfoProvider handlerSource = new HandlerInfoProvider(ServiceHandlers.Instance);
// 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;
using Microsoft.Extensions.DependencyInjection;
using Avalanche.Module;
public class service_construction
{
public static async Task Run()
{
{
// Create service
// <00>
IService service = Services.Create(ServiceHandlers.Instance, CachePolicies.Default);
// </00>
Console.WriteLine(service);
}
{
// Create service
// <00B>
IService service = Services.Create(ServiceHandlers.Instance);
// </00B>
}
{
// <01>
// Create handler list
List<object> handlers = new List<object>();
// Add handlers
handlers.AddRange(ServiceHandlers.Instance);
handlers.Add(Avalanche.Emit.Module.Instance);
// Create service
IService service = Services.Create(handlers);
// </01>
Console.WriteLine(service);
}
{
// Create service
// <02>
IService service = Services.Create(Avalanche.Emit.Module.Instance);
// </02>
}
{
// Create service without cache
// <03>
IService service = Services.CreateWithoutCache(Avalanche.Emit.Module.Instance);
// </03>
}
{
// <04>
// Create service for specific type
IService<TypeRequest, Type> service = Services.Create<TypeRequest, Type>(ServiceHandlers.Instance);
// Query
Type? type = service.Get("System.String");
// </04>
}
{
// <05>
// Create handler
IHandlerBase logger = new MyHandler();
// Create service for specific type
IService service = Services.Create((ServiceHandlers.Instance, logger));
// Query
Type? type = service.Get<TypeRequest, Type>("System.String");
// </05>
}
{
// <06>
// Create handler as delegate
Action<IQuery> logger = q => Console.WriteLine(q.Request);
// Create service for specific type
IService service = Services.Create((ServiceHandlers.Instance, logger));
// Query
Type? type = service.Get<TypeRequest, Type>("System.String");
// </06>
}
{
// <07>
// Create service descriptor
ServiceDescriptor listService = ServiceDescriptor.Transient(typeof(IList<>), typeof(List<>));
// Create service for specific type
IService service = Services.Create((ServiceHandlers.Instance, listService));
// Query for a new transient list
IList<int> ints = service.GetRequired<ServiceRequest<IList<int>>, IList<int>>(default);
// </07>
}
{
// Create service
// <10>
IService service = new ServiceBuilder()
.AddHandlers(ServiceHandlers.Instance)
.Build();
// </10>
}
{
// Create service
// <10b>
IService service = new ServiceBuilderBase()
.Defaults()
.AddHandlers(ServiceHandlers.Instance)
.Build();
// </10b>
}
{
// Create service
// <11>
IService service = new ServiceBuilder()
.AddHandlers(ServiceHandlers.Instance)
.Build();
// </11>
}
{
// Create service
// <12>
IService service = new ServiceBuilder()
.AddHandlers<ServiceHandlers>()
// </12>
.Build();
}
{
// Create service without cache
// <13>
IService service = new ServiceBuilder()
.WithoutCache()
// </13>
.AddHandlers(ServiceHandlers.Instance)
.Build();
}
{
// Create service for specific requests only
// <14>
IService<TypeRequest, Type> service = new ServiceBuilder()
.AddHandlers(ServiceHandlers.Instance)
.Build<TypeRequest, Type>();
// </14>
}
{
// <21>
// Adapt to IHandlerInfoProvider
IHandlerInfoProvider handlerSource = new HandlerInfoProvider(ServiceHandlers.Instance);
// 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.MessageDescription.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.MessageDescription.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));
}
}
// <99>
public class MyHandler : IHandler<object, object>
{
[Order(1_000_000L)]
public void Handle(IQuery<object, object> query) => WriteLine(query.Request);
}
// </99>
}