异常描述
最近使用Redis发现了一个十分诡异的异常,异常如下:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: “StackExchange.Redis.IBatch”未包含“HashSetAsync”的定义
在 CallSite.Target(Closure , CallSite , IBatch , String , String , Object )
在 System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid4[T0,T1,T2,T3](CallSite site, T0 arg0, T1 arg1, T2 arg2, T3 arg3)
在 DbCommandExecutor.RunCommand(RedisCmd cmdInfo, Boolean isMutiWrite)
原因分析
乍一看,似乎是引用的类库存在问题,不包含HashSetAsync的定义,但通过dotPeek反编译发现“HashSetAsync”方法是确实存在的,并非问题所在,再仔细查看RuntimeBinderException产生的原因有两种:
- 第一种:'Microsoft.CSharp.RuntimeBinder.Binder' is not defined or imported,该异常是由于
Microsoft.CSharp
引用缺失导致,直接引用即可; - 第二种:是因为匿名类型不能跨程序集,需要在源程序集中引入
[assembly: InternalsVisibleTo("XXX.XXX.XXX")]
分析代码发现,因为某些不可描述的原因,我使用了dymaic类型:
/// <summary>
/// Redis执行参数。
/// </summary>
public class RedisParam
{
/// <summary>
/// Redis 键。
/// </summary>
public string Key { get; set; }
/// <summary>
/// Redis 复合结构中的键。
/// </summary>
public string StructKey { get; set; }
/// <summary>
/// 数据结构中的值。
/// </summary>
public dynamic StructVal { get; set; }
}
不过RedisHash本身就是一个string类型的field和value的映射表,略做调整,并把dynamic改为string,算是解决了,这个问题本身涉及到了本人的知识盲区和设计上的失误导致的,小计一笔,避免再犯。