MethodScorable.cs
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license.
4 //
5 // Microsoft Bot Framework: http://botframework.com
6 //
7 // Bot Builder SDK GitHub:
8 // https://github.com/Microsoft/BotBuilder
9 //
10 // Copyright (c) Microsoft Corporation
11 // All rights reserved.
12 //
13 // MIT License:
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33 
34 using System;
35 using System.Collections.Generic;
36 using System.Linq;
37 using System.Reflection;
38 using System.Text;
39 using System.Threading.Tasks;
40 using System.Threading;
43 
44 namespace Microsoft.Bot.Builder.Scorables
45 {
50  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
51  [Serializable]
52  public sealed class MethodBindAttribute : Attribute
53  {
54  }
55 
60  [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
61  [Serializable]
62  public sealed class EntityAttribute : Attribute
63  {
67  public readonly string Name;
68 
73  public EntityAttribute(string name)
74  {
75  SetField.NotNull(out this.Name, nameof(name), name);
76  }
77  }
78 }
79 
80 namespace Microsoft.Bot.Builder.Scorables.Internals
81 {
82  public sealed class MethodScorableFactory : IScorableFactory<IResolver, IBinding>
83  {
85  {
86  var specs =
87  from method in methods
88  from bind in InheritedAttributes.For<MethodBindAttribute>(method)
89  select new { method, bind };
90 
91  var scorables = from spec in specs
92  select new MethodScorable(spec.method);
93 
94  var all = scorables.ToArray().Fold(BindingComparer.Instance);
95  return all;
96  }
97  }
98 
99  [Serializable]
100  public abstract class MethodScorableBase : ScorableBase<IResolver, IBinding, IBinding>
101  {
102  public abstract MethodBase Method { get; }
103 
104  public override string ToString()
105  {
106  return $"{this.GetType().Name}({this.Method.Name})";
107  }
108 
109  protected override bool HasScore(IResolver resolver, IBinding state)
110  {
111  return state != null;
112  }
113 
114  protected override IBinding GetScore(IResolver resolver, IBinding state)
115  {
116  return state;
117  }
118 
119  protected override Task PostAsync(IResolver item, IBinding state, CancellationToken token)
120  {
121  try
122  {
123  return state.InvokeAsync(token);
124  }
125  catch (OperationCanceledException error)
126  {
127  return Task.FromCanceled(error.CancellationToken);
128  }
129  catch (Exception error)
130  {
131  return Task.FromException(error);
132  }
133  }
134 
135  protected override Task DoneAsync(IResolver item, IBinding state, CancellationToken token)
136  {
137  return Task.CompletedTask;
138  }
139  }
140 
144  [Serializable]
145  public sealed class MethodScorable : MethodScorableBase
146  {
147  private readonly MethodBase method;
148  public MethodScorable(MethodInfo method)
149  {
150  SetField.NotNull(out this.method, nameof(method), method);
151  }
152 
153  public override MethodBase Method => this.method;
154 
155  protected override Task<IBinding> PrepareAsync(IResolver item, CancellationToken token)
156  {
157  try
158  {
159  IBinding binding;
160  if (Binder.Instance.TryBind(this.method, item, out binding))
161  {
162  return Task.FromResult(binding);
163  }
164  else
165  {
166  return Tasks<IBinding>.Null;
167  }
168  }
169  catch (OperationCanceledException error)
170  {
171  return Task.FromCanceled<IBinding>(error.CancellationToken);
172  }
173  catch (Exception error)
174  {
175  return Task.FromException<IBinding>(error);
176  }
177  }
178  }
179 
180  [Serializable]
181  public sealed class DelegateScorable : MethodScorableBase
182  {
183  private readonly Delegate lambda;
184  public DelegateScorable(Delegate lambda)
185  {
186  SetField.NotNull(out this.lambda, nameof(lambda), lambda);
187  }
188 
189  public override MethodBase Method => this.lambda.Method;
190 
191  protected override Task<IBinding> PrepareAsync(IResolver item, CancellationToken token)
192  {
193  try
194  {
195  IBinding binding;
196  if (Binder.Instance.TryBind(this.lambda, item, out binding))
197  {
198  return Task.FromResult(binding);
199  }
200  else
201  {
202  return Tasks<IBinding>.Null;
203  }
204  }
205  catch (OperationCanceledException error)
206  {
207  return Task.FromCanceled<IBinding>(error.CancellationToken);
208  }
209  catch (Exception error)
210  {
211  return Task.FromException<IBinding>(error);
212  }
213  }
214  }
215 }
bool TryBind(MethodBase method, IResolver resolver, out IBinding binding)
static readonly Task< T > Null
Definition: Tasks.cs:46
readonly string Name
The entity name.
override Task< IBinding > PrepareAsync(IResolver item, CancellationToken token)
IScorable< Item, Score > ScorableFor(IEnumerable< MethodInfo > methods)
EntityAttribute(string name)
Construct the EntityAttribute.
Allow the scoring of items, with external comparison of scores, and enable the winner to take some ac...
Definition: Scorable.cs:49
Allow the resolution of values based on type and optionally tag.
Allow for static type checking of opaque state for convenience of scorable implementations.
Definition: ScorableBase.cs:55
Namespace for internal scorable implementation that is not useful for most developers and may change ...
Namespace for scorable interfaces, classes and compositions.
Namespace for internal machinery that is not useful for most developers and may change in the future...
Represents a binding of arguments to a method&#39;s parameters.
Definition: Binding.cs:47
Scorable to represent binding arguments to a method&#39;s parameters.
This attribute is used to specify that a method will participate in the scoring process for overload ...
override Task< IBinding > PrepareAsync(IResolver item, CancellationToken token)
override Task PostAsync(IResolver item, IBinding state, CancellationToken token)
This attribute is used to specify that a method parameter is bound to an entity that can be resolved ...
override Task DoneAsync(IResolver item, IBinding state, CancellationToken token)
override bool HasScore(IResolver resolver, IBinding state)
static readonly IComparer< IBinding > Instance
Namespace for the internal fibers machinery that is not useful for most developers and may change in ...
override IBinding GetScore(IResolver resolver, IBinding state)
Helper methods to enumerate inherited attributes for a method.
Root namespace for the Microsoft Bot Builder SDK.