BindingComparer.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.Runtime.Serialization;
38 using System.Text;
39 using System.Threading;
40 using System.Threading.Tasks;
41 
42 namespace Microsoft.Bot.Builder.Scorables.Internals
43 {
44  public sealed class BindingComparer : IComparer<IBinding>
45  {
46  public static readonly IComparer<IBinding> Instance = new BindingComparer();
47 
48  private BindingComparer()
49  {
50  }
51 
52  private bool TryCompareParameterTypeAssignability(IReadOnlyList<Type> one, IReadOnlyList<Type> two, int index, out int compare)
53  {
54  var l = one[index];
55  var r = two[index];
56  if (l.Equals(r))
57  {
58  compare = 0;
59  return true;
60  }
61  if (l.IsAssignableFrom(r))
62  {
63  compare = -1;
64  return true;
65  }
66  else if (r.IsAssignableFrom(l))
67  {
68  compare = +1;
69  return true;
70  }
71 
72  compare = 0;
73  return false;
74  }
75 
76  public static int UpdateComparisonConsistently(IBinding one, IBinding two, int compareOld, int compareNew)
77  {
78  if (compareOld == 0)
79  {
80  return compareNew;
81  }
82  else if (compareNew == 0)
83  {
84  return compareOld;
85  }
86  else if (compareNew == compareOld)
87  {
88  return compareOld;
89  }
90  else
91  {
92  throw new MethodResolutionException("inconsistent parameter overrides", one, two);
93  }
94  }
95 
96  int IComparer<IBinding>.Compare(IBinding one, IBinding two)
97  {
98  int compare = 0;
99 
100  var oneTypes = one.Method.CachedParameterTypes();
101  var twoTypes = two.Method.CachedParameterTypes();
102 
103  var count = Math.Min(oneTypes.Count, twoTypes.Count);
104  for (int index = 0; index < count; ++index)
105  {
106  int parameter;
107  if (TryCompareParameterTypeAssignability(oneTypes, twoTypes, index, out parameter))
108  {
109  compare = UpdateComparisonConsistently(one, two, compare, parameter);
110  }
111  else
112  {
113  throw new MethodResolutionException("inconsistent parameter types", one, two);
114  }
115  }
116 
117  int length = oneTypes.Count.CompareTo(twoTypes.Count);
118  compare = UpdateComparisonConsistently(one, two, compare, length);
119  return compare;
120  }
121  }
122 
123  [Serializable]
124  public sealed class MethodResolutionException : Exception
125  {
126  public MethodResolutionException(string message, IBinding one, IBinding two)
127  : base($"{message}: {one} and {two}")
128  {
129  }
130 
131  private MethodResolutionException(SerializationInfo info, StreamingContext context)
132  : base(info, context)
133  {
134  }
135  }
136 }
MethodResolutionException(string message, IBinding one, IBinding two)
static int UpdateComparisonConsistently(IBinding one, IBinding two, int compareOld, int compareNew)
Represents a binding of arguments to a method&#39;s parameters.
Definition: Binding.cs:47