Cache.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.Threading;
39 using System.Threading.Tasks;
40 
41 namespace Microsoft.Bot.Builder.Internals.Fibers
42 {
43  public interface ICache<C, K, V>
44  {
45  Task<V> GetOrAddAsync(C context, K key, Func<C, K, CancellationToken, Task<V>> make, CancellationToken token);
46  }
47 
48  public sealed class NullCache<C, K, V> : ICache<C, K, V>
49  {
50  Task<V> ICache<C, K, V>.GetOrAddAsync(C context, K key, Func<C, K, CancellationToken, Task<V>> make, CancellationToken token)
51  {
52  try
53  {
54  return make(context, key, token);
55  }
56  catch (OperationCanceledException error)
57  {
58  return Task.FromCanceled<V>(error.CancellationToken);
59  }
60  catch (Exception error)
61  {
62  return Task.FromException<V>(error);
63  }
64  }
65  }
66 
67  [Serializable]
68  public sealed class DictionaryCache<C, K, V> : ICache<C, K, V>, ISerializable
69  {
70  private readonly IEqualityComparer<K> comparer;
71 
72  [NonSerialized]
73  private readonly Dictionary<K, Task<V>> cache;
74  public DictionaryCache(IEqualityComparer<K> comparer)
75  {
76  SetField.NotNull(out this.comparer, nameof(comparer), comparer);
77  this.cache = new Dictionary<K, Task<V>>(comparer);
78  }
79  private DictionaryCache(SerializationInfo info, StreamingContext context)
80  {
81  SetField.NotNullFrom(out this.comparer, nameof(this.comparer), info);
82  this.cache = new Dictionary<K, Task<V>>(comparer);
83  }
84 
85  void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
86  {
87  info.AddValue(nameof(this.comparer), comparer);
88  }
89 
90  Task<V> ICache<C, K, V>.GetOrAddAsync(C context, K key, Func<C, K, CancellationToken, Task<V>> make, CancellationToken token)
91  {
92  try
93  {
94  Task<V> task;
95  lock (this.cache)
96  {
97  if (!this.cache.TryGetValue(key, out task))
98  {
99  // TODO: properly propagate the CancellationToken
100  task = make(context, key, token);
101  this.cache.Add(key, task);
102  }
103  }
104 
105  return task;
106  }
107  catch (OperationCanceledException error)
108  {
109  return Task.FromCanceled<V>(error.CancellationToken);
110  }
111  catch (Exception error)
112  {
113  return Task.FromException<V>(error);
114  }
115  }
116  }
117 }
Task< V > GetOrAddAsync(C context, K key, Func< C, K, CancellationToken, Task< V >> make, CancellationToken token)
DictionaryCache(IEqualityComparer< K > comparer)
Definition: Cache.cs:74