2016-02-19 3 views
-1

Мне нужно хранить пары ключ-значение в базе данных. Значение может быть одним из типов: bool, int, double, string, DateTime. В классе ниже Set<T> -операция работает, но Get<T> выбрасывает InvalidCastException.Получение примитивного типа из объекта с использованием общего

public class PersistedKeyValueStorage 
{ 
    AppDbContext _dbContext; 
    public PersistedKeyValueStorage() : this(new AppDbContext()) { } 
    public PersistedKeyValueStorage(AppDbContext dbContext) 
    { 
     _dbContext = dbContext; 
    } 

    public T Get<T>(string Key) { 
     var record=_dbContext.Set<StoredKeyValueItem>().FirstOrDefault(p => p.Key == Key); 

     if (record != null) return (T)(object)(record.Value); // here is error 
      return default(T);     
    } 

    public void Set<T>(string Key, T Value) where T : struct    
    { 
     var record = _dbContext.Set<StoredKeyValueItem>().FirstOrDefault(p => p.Key == Key); 
     if (record != null) record.Value = Value.ToString(); 

     else _dbContext.Set<StoredKeyValueItem>().Add(new StoredKeyValueItem { Key = Key, Value = Value.ToString() }); 

     _dbContext.SaveChanges(); 
    } 
} 
// class usage 

var skvs = new PersistedKeyValueStorage(); 
skvs.Set("test.int", (int)123); 
skvs.Set("test.boolean", true); 
skvs.Set("test.datetime", DateTime.Now); 

ViewBag.testint= skvs.Get<int>("test.int"); 
ViewBag.testbool = skvs.Get<Boolean>("test.boolean"); 
ViewBag.testdate= skvs.Get<DateTime>("test.datetime"); 
+0

Я подозреваю, что это будет работать, делая это:. 'Вар запись = _dbContext.Set () FirstOrDefault (р => p.Key == Key) .Value' –

+1

И' 'Set не работает, если 'Get ' также работает. Это как сказать, что ваш код шифрования работает нормально, вы просто не можете расшифровать значение, это не имеет никакого значения. Они должны работать, или никто из них не работает, потому что они являются пакетной сделкой. Причина, по которой я говорю это, состоит в том, что для того, чтобы «Get » работать, вам может потребоваться изменить «Установить », чтобы не использовать строки. –

ответ

1

Вы сохраняете все значения как строки в своем магазине.

Итак, когда вы их вернете, они будут струнами.

Для того, чтобы получить от object до T, то фактический объект должен быть либо:

  • типа значения типа T
  • ссылочного типа, который может быть переосмысленным, как T

int - это тип значения, но при выполнении (int)obj вы можете только unbox значение в и он должен быть int. В вашем случае это string. Это не сработает.

Вместо этого вам придется использовать уровень конверсии, который преобразуется в ваш тип хранилища и обратно, string.

Для некоторых типов вы можете попытаться изменить свой код на этот:

return (T)Convert.ChangeType(record.Value, typeof(T)); 

Но это не будет обрабатывать все типы, которые имеют право на T.

+0

Convert.ChangeType работает на всех типах, которые перечислены, спасибо! –

Смежные вопросы