«StackExchange.Redis.ITransaction» не содержит определения для «StringSetAsync».

Я использую транзакцию в Redis и использую провайдера StackExchange.Redis.

У меня есть большая партия операций StringSetAsync для транзакции.

И у меня есть ошибка при использовании StringSetAsync:

Исключение RuntimeBinderException было перехвачено

«StackExchange.Redis.ITransaction» не содержит определения для «StringSetAsync».

Трассировки стека:

в CallSite.Target(Closure, CallSite, ITransaction, String, Object) в Repository.RedisDatabaseContextBase.SetRecord(IBasicRedisEntity redisEntity, Boolean isNewRecord)

====

Добавлен:

Вот пример кода, который отражает проблему. Марк был прав, все дело в динамике.

try
{
  ConnectionMultiplexer cm = ConnectionMultiplexer.Connect("localhost:6380,allowAdmin=true");
  var db = cm.GetDatabase();

  ITransaction transaction = db.CreateTransaction();

  dynamic pp = new byte[5] {1, 2, 3, 4, 5};

  transaction.StringSetAsync("test", pp);

  if (transaction.Execute())
  {
    Console.Write("Committed");
  }
  else
  {
    Console.Write("UnCommitted");
  }

  Console.ReadLine();
}
catch (Exception e)
{
  Console.WriteLine(e);
}

person Anton Norko    schedule 21.01.2015    source источник
comment
RuntimeBinderException предполагает, что вы используете dynamic — это правильно?   -  person Marc Gravell    schedule 21.01.2015
comment
Нет, я использую дженерики. Но в итоге все равно просто: transaction.StringSetAsync(key, value); // ошибка   -  person Anton Norko    schedule 22.01.2015
comment
Ненавижу это говорить, но упоминание CallSite в таком виде: сильно предполагает, что здесь играет роль dynamic — в этом случае да: в нескольких сценариях (например, явная реализация) это не сработает. У вас есть пример кода, где это происходит? Включая типы любых переменных (например, если у вас есть obj.StringSetAsync(...), что такое obj?)   -  person Marc Gravell    schedule 22.01.2015
comment
Да, мой плохой. Пожалуйста, просмотрите мой отредактированный пост, пожалуйста.   -  person Anton Norko    schedule 22.01.2015


Ответы (1)


В некотором смысле это правильно: не существует перегрузки, которая занимает byte[]. Есть вариант, который занимает RedisValue, но это не одно и то же. dynamic разрешение метода может быть глючным - как для явных реализаций интерфейса, так и для операторов преобразования: здесь применимы оба!

Я бы предложил:

object pp = new byte[5] {1, 2, 3, 4, 5};

if(pp is byte[])
    transaction.StringSetAsync("test", (byte[])pp);
else if (pp is string)
    transaction.StringSetAsync("test", (string)pp);
else if (pp is RedisValue)
    transaction.StringSetAsync("test", (RedisValue)pp);
else
    throw new NotSupportedException(
        "Value is not usable: " + pp.GetType().FullName);

Альтернативой может быть:

dynamic pp = new byte[5] {1, 2, 3, 4, 5};
transaction.StringSetAsync("test", (RedisValue)pp);

Это должно работать в теории, но по-прежнему немного ненужно, IMO.

person Marc Gravell    schedule 22.01.2015
comment
На практике это тоже работает, и я с вами согласен: лучше проверяйте приведение, чтобы не допустить ошибок. - person Anton Norko; 22.01.2015