Remove remaining strong ties to StoreItem

* `BotState<StateT>` stil assumed state entries would all be
`StoreItem` subclasses when working with ETag concepts. Updated to
detect if `IStoreItem` dynamically now.
  * Add restrictions for all state types to be `class` subtypes so we
can use `as` operators for simple casting, plus allowing `struct` types
would lead to strange behavior and have performance implications
(boxing).
This commit is contained in:
Drew Marsh 2018-03-06 21:47:22 -08:00
Родитель 995b72f2c1
Коммит 57d50b20f2
2 изменённых файлов: 17 добавлений и 15 удалений

Просмотреть файл

@ -1,8 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Threading.Tasks;
namespace Microsoft.Bot.Builder
{
@ -49,7 +49,7 @@ namespace Microsoft.Bot.Builder
/// </summary>
public string eTag { get; set; }
public T ToObject<T>()
public T ToObject<T>() where T : class
{
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(this, serializationSettings), serializationSettings);
}
@ -57,15 +57,15 @@ namespace Microsoft.Bot.Builder
public class StoreItems : FlexObject
{
public T Get<T>(string name)
public T Get<T>(string name) where T : class
{
if (this.TryGetValue(name, out dynamic value) && value != null)
return value.ToObject<T>();
return default(T);
this.TryGetValue(name, out object value);
return value as T;
}
}
public class StoreItems<StoreItemT> : StoreItems
public class StoreItems<StoreItemT> : StoreItems where StoreItemT : class
{
}
@ -85,8 +85,7 @@ namespace Microsoft.Bot.Builder
/// <param name="storage"></param>
/// <param name="keys"></param>
/// <returns></returns>
public static async Task<StoreItems<StoreItemT>> Read<StoreItemT>(this IStorage storage, params string[] keys)
where StoreItemT : StoreItem
public static async Task<StoreItems<StoreItemT>> Read<StoreItemT>(this IStorage storage, params string[] keys) where StoreItemT : class
{
var storeItems = await storage.Read(keys).ConfigureAwait(false);
var newResults = new StoreItems<StoreItemT>();

Просмотреть файл

@ -19,7 +19,7 @@ namespace Microsoft.Bot.Builder.Middleware
/// </summary>
/// <typeparam name="StateT"></typeparam>
public abstract class BotState<StateT> : IContextCreated, ISendActivity
where StateT : new()
where StateT : class, new()
{
private readonly StateSettings _settings;
private readonly IStorage _storage;
@ -86,7 +86,10 @@ namespace Microsoft.Bot.Builder.Middleware
{
foreach (var item in changes)
{
((StoreItem)changes[item.Key]).eTag = "*";
if(item.Value is IStoreItem valueStoreItem)
{
valueStoreItem.eTag = "*";
}
}
}
@ -100,7 +103,7 @@ namespace Microsoft.Bot.Builder.Middleware
/// </summary>
/// <typeparam name="StateT"></typeparam>
public class ConversationState<StateT> : BotState<StateT>
where StateT : new()
where StateT : class, new()
{
public static string PropertyName = $"ConversationState:{typeof(ConversationState<StateT>).Namespace}.{typeof(ConversationState<StateT>).Name}";
@ -124,7 +127,7 @@ namespace Microsoft.Bot.Builder.Middleware
/// </summary>
/// <typeparam name="StateT"></typeparam>
public class UserState<StateT> : BotState<StateT>
where StateT : new()
where StateT : class, new()
{
public static readonly string PropertyName = $"UserState:{typeof(UserState<StateT>).Namespace}.{typeof(UserState<StateT>).Name}";
@ -146,13 +149,13 @@ namespace Microsoft.Bot.Builder.Middleware
public static class StateContextExtensions
{
public static T GetConversationState<T>(this IBotContext context)
where T : new()
where T : class, new()
{
return ConversationState<T>.Get(context);
}
public static T GetUserState<T>(this IBotContext context)
where T : new()
where T : class, new()
{
return UserState<T>.Get(context);
}