调用MethodInfo.MakeGenericMethod时,此键错误是什么意思?

今天我从一些旧的动态转换代码中得到了这个错误(我已经改变了最后一行并省略了堆栈跟踪的其余部分):

Item has already been added. Key in dictionary: 'Int32 Count[Object](System.Collections.Generic.IEnumerable`1[System.Object])' Key being added: 'Int32 Count[Object](System.Collections.Generic.IEnumerable`1[System.Object])' ---> System.ArgumentException: Item has already been added. Key in dictionary: 'Int32 Count[Object](System.Collections.Generic.IEnumerable`1[System.Object])' Key being added: 'Int32 Count[Object](System.Collections.Generic.IEnumerable`1[System.Object])' at System.Reflection.CerHashtable`2.Insert(K[] keys, V[] values, Int32& count, K key, V value) at System.Reflection.CerHashtable`2.Preallocate(Int32 count) at System.RuntimeType.RuntimeTypeCache.GetGenericMethodInfo(RuntimeMethodHandle genericMethod) at System.RuntimeType.GetMethodBase(RuntimeTypeHandle reflectedTypeHandle, RuntimeMethodHandle methodHandle) at System.Reflection.RuntimeMethodInfo.MakeGenericMethod(Type[] methodInstantiation) at MyNamespace.CommunicationExtensions.BuildMessage[T](T obj) 

全class

 public static class CommunicationExtensions { static readonly object lockobj = new object(); public static bool CanBuildMessage(this T obj) where T: class { return obj != null && (MessageFactory.MessageBuilders.ContainsKey(obj.GetType())); } public static string BuildMessage(this T obj) { lock (lockobj) { Delegate d; var type = obj.GetType(); if (MessageFactory.MessageBuilders.TryGetValue(type, out d)) { var castMethod = typeof(CommunicationExtensions).GetMethod("Cast").MakeGenericMethod(type); var castedObject = castMethod.Invoke(null, new object[] { obj }); return d.DynamicInvoke(castedObject) as string; } } return null; } public static T Cast(object o) { return (T)o; } } 

MessageFactory.MessageBuilders是一个Dictionary<Type,Func>包含编译的lambda表达式,这些表达式根据需要延迟构建,以将Message事件(基于EventArgs的简单自动属性类)转换为其他系统中使用的字符串格式。 我认为这不重要。 我认为导致此问题的唯一代码是:

 public static class CastError{ public static void GetCast(this T obj) { var type = obj.GetType(); var castMethod = typeof(CastError).GetMethod("Cast").MakeGenericMethod(type); //... } public static T Cast(object o) { return (T)o; } } 

它看起来像是框架中的失败,无法正确锁定MakeGenericMethod的内部。

当调用MakeGenericMethod时,框架应该使用指定的generics参数创建方法的新版本,或者如果在创建该generics方法之前使用了相同的generics参数类型,那么它应该返回先前的 – 生成方法。 看起来你遇到了一个边缘情况,在多个线程上调用MakeGenericMethod可能导致竞争条件,其中两个线程都认为该方法尚未生成并继续生成它,然后随后冲突存储生成的方法以供将来调用。

也就是说,在这种情况下,看起来它都处于锁定状态,所以我并不完全相信这也是问题所在。

我将它与MSFT一起提交为一个bug,除非其他人可以解释这是预期的行为。