microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
next/core

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Libraries/Microsoft.Teams.Apps/Routing/Route.cs

100lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT License.
3
4using System.Reflection;
5
6using Microsoft.Teams.Api.Activities;
7using Microsoft.Teams.Apps.Activities;
8using Microsoft.Teams.Apps.Annotations;
9using Microsoft.Teams.Common.Extensions;
10
11namespace Microsoft.Teams.Apps.Routing;
12
13public interface IRoute
14{
15 public string? Name { get; }
16 public RouteType Type { get; }
17
18 public bool Select(IActivity activity);
19 public Task<object?> Invoke(IContext<IActivity> context);
20}
21
22public class Route : IRoute
23{
24 public required string Name { get; set; }
25 public RouteType Type { get; set; } = RouteType.User;
26 public required Func<IActivity, bool> Selector { get; set; }
27 public required Func<IContext<IActivity>, Task<object?>> Handler { get; set; }
28
29 public bool Select(IActivity activity) => Selector(activity);
30 public async Task<object?> Invoke(IContext<IActivity> context) => await Handler(context);
31}
32
33public class AttributeRoute : IRoute
34{
35 public string? Name => Attr.Name?.Value;
36 public RouteType Type { get; set; } = RouteType.User;
37 public required ActivityAttribute Attr { get; set; }
38 public required MethodInfo Method { get; set; }
39 public object? Object { get; set; }
40
41 public bool Select(IActivity activity) => Attr.Select(activity);
42 public ValidationResult Validate()
43 {
44 var result = new ValidationResult();
45
46 foreach (var param in Method.GetParameters())
47 {
48 var attribute = param.GetCustomAttribute<ContextAccessorAttribute>(true);
49 var generic = param.ParameterType.GenericTypeArguments.FirstOrDefault();
50 var isContext = generic?.IsAssignableTo(Attr.Type) ?? false;
51
52 if (attribute is null && !isContext)
53 {
54 result.AddError(param.Name ?? "??", "type must be `IContext<TActivity>` or an `IContext` accessor attribute");
55 }
56 }
57
58 return result;
59 }
60
61 public Task<object?> Invoke(IContext<IActivity> context)
62 {
63 var args = Method.GetParameters().Select(param =>
64 {
65 var attribute = param.GetCustomAttribute<ContextAccessorAttribute>(true);
66 return attribute is null ? Attr.Coerce(context) : attribute.GetValue(context, param);
67 });
68
69 return Method.InvokeAsync(Object, args?.ToArray());
70 }
71
72 public class ValidationResult
73 {
74 /// <summary>
75 /// the errors that were found
76 /// </summary>
77 public IList<ParameterError> Errors { get; set; } = [];
78
79 /// <summary>
80 /// is the result valid
81 /// </summary>
82 public bool Valid => Errors.Count == 0;
83
84 /// <summary>
85 /// combine all the errors into
86 /// one message string
87 /// </summary>
88 public override string ToString() => string.Join(Environment.NewLine, Errors.Select(err => $"{err.Name} => {err.Message}"));
89
90 /// <summary>
91 /// add a parameter error to the result
92 /// </summary>
93 public void AddError(string name, string message)
94 {
95 Errors.Add(new(name, message));
96 }
97
98 public record ParameterError(string Name, string Message);
99 }
100}