- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想在运行时创建类型并通过 Activator.CreateInstance 实例化它。我正在使用 Refletion.Emit 来执行此操作,当创建和实例化类型的方法在单个线程中运行时,一切正常。然而,当我尝试在多个线程中运行相同的方法时,会抛出一个 ArgumentException。
代码类似于:
class TypeBuilder
public IMyType Build() {
Type type = GetDynamicType("MyDynamicType");
IMyType myType = (IMyType) Activator.CreateInstance(type);
return myType;
}
Type GetDynamicType(string typeName) {
// define the module builder...
ModuleBuilder module = ...
Type type = module.GetType(typeName);
if (type == null) {
type = MakeDynamicType(typeName);
}
retyrn type;
}
Type MakeDynamicType(string typeName) {
lock(lock_) { // lock_ is a static variable
// ensure that the type was not already created by another thread.
Type type =
module
.GetType(typeName);
if (type != null) {
return type;
}
// define the type builder...
TypeBuilder builder = ...
// define the type body...
return type.CreateType();
}
}
}
一些观察:
更新 1:
异常消息是:“类型必须是运行时提供的类型。”
更新 2:
完整的源代码托管在 GitHub 上
最佳答案
也许是一个迟到的答案,但无论如何。
在您的代码中,GetDynamicType
不是线程安全的,有两个未处理的竞争条件。其中比较有趣的是:
一个线程用ModuleBuilder.DefineType(...)
定义了一个新类型.它得到 TypeBuilder
然后使用它来构建类型的对象。
同时,另一个线程调用ModuleBuilder.GetType(...)
并获得 Type
它寻找的对象……至少它是这么认为的。它假设它得到了 RuntimeType
,但实际上,它得到了 TypeBuilder
由第一个线程构建。
仅当第一个线程调用TypeBuilder.CreateType()
时, TypeBuilder
替换为相应的 RuntimeType
在ModuleBuilder
.
所以你最终会尝试 Activator.CreateInstance
的 TypeBuilder
,它会抛出“类型必须是运行时提供的类型”异常。
我建议重写 GetDynamicType
函数并使用 ConcurrentDictionary<string, Type>
与 MakeDynamicType
作为值(value)工厂:
private readonly ConcurrentDictionary<string, Type> _dynamicTypesByName =
new ConcurrentDictionary<string, Type>();
Type GetDynamicType(string typeName) {
// define the module builder...
ModuleBuilder module = ...
return _dynamicTypesByName.GetOrAdd(typeName, MakeDynamicType);
}
关于c# - 从 TypeBuilder.CreateType 返回的类型的 Activator.CreateInstance 抛出 ArgumentException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30201509/
尝试将应用程序从 .net 4.5 移植到客户端的 .net 核心。我注意到 CreateType 不再是 TypeBuilder 的一部分。我搜索了多个新的反射库,但没有成功。有谁知道如何移植这个?
我想在运行时创建类型并通过 Activator.CreateInstance 实例化它。我正在使用 Refletion.Emit 来执行此操作,当创建和实例化类型的方法在单个线程中运行时,一切正常。然
在开始之前,这是我关于 SO 的第一个问题。因此,可能存在错误或缺少有关该问题的信息。如果我需要更正某些内容,请告诉我。谢谢。 使用 TypeBuilder,我正在构建一个实现包含方法的接口(inte
我是一名优秀的程序员,十分优秀!