今天,我从一些旧的动态转换代码中收到此错误(我更改了最后一行并省略了堆栈跟踪的其余部分):
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)
全类
public static class CommunicationExtensions {
static readonly object lockobj = new object();
public static bool CanBuildMessage<T>(this T obj) where T: class {
return obj != null && (MessageFactory.MessageBuilders.ContainsKey(obj.GetType()));
}
public static string BuildMessage<T>(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<T>(object o) {
return (T)o;
}
}
MessageFactory.MessageBuilders
是 Dictionary<Type,Func<Type,string>>
包含已编译的 lambda 表达式,这些表达式根据需要延迟构建,以将 Message 事件(基于 EventArgs 的简单自动属性类)转换为其他系统中使用的字符串格式。但我认为这些都不重要。我认为导致此问题的唯一必要代码是:
public static class CastError{
public static void GetCast<T>(this T obj) {
var type = obj.GetType();
var castMethod = typeof(CastError).GetMethod("Cast").MakeGenericMethod(type);
//...
}
public static T Cast<T>(object o) {
return (T)o;
}
}
最佳答案
看起来框架未能正确锁定 MakeGenericMethod 的内部。
当调用 MakeGenericMethod 时,框架应该使用指定的泛型参数创建该方法的新版本,或者如果之前已使用相同的泛型参数类型来创建该泛型方法,则它应该返回先前生成的方法。看起来您遇到了一个边缘情况,在多个线程上调用 MakeGenericMethod
可能会导致竞争条件,两个线程都认为该方法尚未生成并继续生成它,然后随后发生冲突存储生成的方法以供将来调用。
也就是说,在这种情况下,看起来一切都在锁中,所以我也不完全相信这就是问题所在。
我会将其作为错误向 MSFT 归档,除非其他人可以解释这是如何预期的行为。
关于c# - 调用 MethodInfo.MakeGenericMethod 时出现此关键错误意味着什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9419464/