Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
编译的Lambda和Activator.CreateInstance()_Lambda_Delegates_Expression Trees_Concurrentdictionary_Createinstance - Fatal编程技术网

编译的Lambda和Activator.CreateInstance()

编译的Lambda和Activator.CreateInstance(),lambda,delegates,expression-trees,concurrentdictionary,createinstance,Lambda,Delegates,Expression Trees,Concurrentdictionary,Createinstance,我试图在以下循环(简化)的每次迭代中降低调用Activator.CreateInstance()的性能成本: 根据我读到的内容,最好的方法是编译一个委托并缓存它。这将在第一次迭代时(在构建委托时)减慢速度,但会极大地提高后续迭代的性能。这是可以接受的,因为我迭代了1000次以上。为了使事情进一步复杂化,我并行执行这个循环,所以任何缓存机制都必须是线程安全的(ConcurentDictionary)。将循环中的方法转换为泛型是不可能的,因为我要传递给Activator.CreateInstance

我试图在以下循环(简化)的每次迭代中降低调用Activator.CreateInstance()的性能成本:

根据我读到的内容,最好的方法是编译一个委托并缓存它。这将在第一次迭代时(在构建委托时)减慢速度,但会极大地提高后续迭代的性能。这是可以接受的,因为我迭代了1000次以上。为了使事情进一步复杂化,我并行执行这个循环,所以任何缓存机制都必须是线程安全的(ConcurentDictionary)。将循环中的方法转换为泛型是不可能的,因为我要传递给Activator.CreateInstance()的类型是由用户通过GUI做出的选择决定的,并传递给我的函数。以下是方法签名供参考:

public static void InsertByTable(IEnumerable<DataTable> chunkedTable, Type type)
公共静态void InsertByTable(IEnumerable chunkedTable,类型)
所以我想做一些类似的事情(这是伪代码):

专用静态只读ConcurrentDictionary缓存构造函数=
新的ConcurrentDictionary();
私有静态对象CreateInstance(类型)
{
if(type==null)
返回;
var constructor=CachedConstructors.GetOrAdd(类型,BuildInstance);
建造师(类型);
}
私有静态Func BuildInstance(类型)
{
}

但我有点不知所措,不知如何实际构建表达式,甚至不知这是否是正确的方法

我认为在这种情况下,建立一个表达式是一种方法。对于通过的每一行,都使用反射来构建对象。那可不便宜。如果您构建了一个表达式来初始化对象,那么只需构建一次表达式,就可以得到一个lambda,它的性能会显著提高

Func创建初始值设定项(数据表,类型)
{
var param=Expression.Parameter(typeof(DataRow),“row”);
var body=Expression.MemberInit(
表达式。新(类型),
来自表.Columns中的DataColumn c
让prop=type.GetProperty(c.ColumnName)
让value=Expression.Convert(
Expression.Property(param,“Item”,Expression.Constant(c.ColumnName)),
prop.PropertyType
)
选择表达式。绑定(属性、值)
);
var expr=Expression.Lambda(body,param);
返回expr.Compile();
}
然后要使用它,只需创建一次,并使用它映射行

var initializer=CreateInitializer(表,typeof(SomeObject));
var data=table.AsEnumerable().Select(初始值设定项).ToList();

这将取决于运行代码的上下文,但如果编译时已知
类型
,则可以将该方法更改为类似
AddRows(…)的通用方法,其中T:new()
,然后只需使用
new T()
代替
Activator.CreateInstance(…)
…我已经更新了我的帖子以包含整个功能。目前,我将该类型作为参数传入,因为该类型是根据用户通过GUI选择的选项确定的。
public static void InsertByTable(IEnumerable<DataTable> chunkedTable, Type type)
private static readonly ConcurrentDictionary<Type, Func<object>> CachedConstructors =
        new ConcurrentDictionary<Type, Func<object>>();

private static object CreateInstance(Type type)
{
    if (type == null)
         return;

    var constructor = CachedConstructors.GetOrAdd(type, BuildInstance);

    constructor(type);
}

private static Func<Type> BuildInstance(Type type)
{
}