Trying to improve a insert method via array binding(Oracle), which will need to put strongly type with Array.
The first step, I need to List<object>
to each property Array
. However, when I use LINQ to Select
the property then ToArray()
, I got an object[]
.
//Reflection
foreach(var prop in typeof(Person).GetProperties())
personList.Select(x => prop.GetValue(x)).ToArray();
It look like can't use generic ToArray<T>()
to handle runtime property type.
Code https://dotnetfiddle.net/7ogYNJ
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
public class Program
{
public static void Main()
{
List<Person> personList = new List<Person>();
personList.Add(new Person(){Name = "aaa", Age = 10});
personList.Add(new Person(){Name = "bbb", Age = 5});
for(int i = 0; i< 10; i++)
{
personList.AddRange(personList);
}
Dictionary<string, PropertyInfo> propDict = typeof(Person).GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CanRead && !p.GetIndexParameters().Any()).AsEnumerable().ToDictionary(x => x.Name, x => x);
int count = personList.Count;
Stopwatch sw = new Stopwatch();
//1. get Object[]
sw.Restart();
foreach(var prop in propDict)
{
var tempArray = personList.Select(x => prop.Value.GetValue(x)).ToArray();
Console.WriteLine(tempArray.GetType().Name);//Object[]
}
sw.Stop();
Console.WriteLine("Spend" + sw.ElapsedMilliseconds + "us");
//2. not work, return Object[]
sw.Restart();
foreach(var prop in propDict)
{
var tempArray = personList.Select(x => Convert.ChangeType(prop.Value.GetValue(x), prop.Value.PropertyType)).ToArray();
Console.WriteLine(tempArray.GetType().Name);//Object[]
}
sw.Stop();
Console.WriteLine("Spend" + sw.ElapsedMilliseconds + "us");
//3. work, via ArrayCopy, try to find other method
sw.Restart();
foreach(var prop in propDict)
{
var tempArray = personList.Select(x => prop.Value.GetValue(x)).ToArray();
Array stronglyTypeArray = Array.CreateInstance(prop.Value.PropertyType, count);
Array.Copy(tempArray, stronglyTypeArray, count);
Console.WriteLine(stronglyTypeArray.GetType().Name);//String[]//Int32[]
}
sw.Stop();
Console.WriteLine("Spend" + sw.ElapsedMilliseconds + "us");
//4. work, if-condition slower than method 3
sw.Restart();
foreach(var prop in propDict)
{
dynamic tempArray;
if(prop.Value.PropertyType == typeof(System.String))
{
tempArray = personList.Select(x => prop.Value.GetValue(x).ToString()).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Boolean))
{
tempArray = personList.Select(x => (bool)prop.Value.GetValue(x)).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Byte))
{
tempArray = personList.Select(x => (byte)prop.Value.GetValue(x)).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Char))
{
tempArray = personList.Select(x => (char)prop.Value.GetValue(x)).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Decimal))
{
tempArray = personList.Select(x => (decimal)prop.Value.GetValue(x)).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Double))
{
tempArray = personList.Select(x => (double)prop.Value.GetValue(x)).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Int16))
{
tempArray = personList.Select(x => (short)prop.Value.GetValue(x)).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Int32))
{
tempArray = personList.Select(x => (int)prop.Value.GetValue(x)).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Int64))
{
tempArray = personList.Select(x => (long)prop.Value.GetValue(x)).ToArray();
}
else if(prop.Value.PropertyType == typeof(System.Single))
{
tempArray = personList.Select(x => (float)prop.Value.GetValue(x)).ToArray();
}
else
{
tempArray = personList.Select(x => prop.Value.GetValue(x)).ToArray();
}
Console.WriteLine(tempArray.GetType().Name);//Object[]
}
sw.Stop();
Console.WriteLine("Spend" + sw.ElapsedMilliseconds + "us");
}
}
In method 2, I try to use Convert.Change
and it is not work.
In method 3, via Array.CreateInstance
and ArrayCopy
, it work.
In method 4, use if-condition to cast, but it is slower than method 3 and can't handle unexpected type.
My candidate is method 3. Is there any more efficient way to get strongly type with Array?
By the way, there is a delegate
method to get property value faster https://stackoverflow.com/a/17440469/12620047
Aucun commentaire:
Enregistrer un commentaire