I want to have two converters like these:
public class PacMan<T2> where T2 : new()
{
public static List<T1> ArrayToList<T1>(T2[] array)
{
var list = new List<T1>(array.Length);
for (int i = 0; i < array.Length; i++) list.Add(array[i]);
return list;
}
public static T2[] ListToArray<T1>(List<T1> list)
{
var array = new T2[list.Count];
for (int i = 0; i < list.Count; i++) array[i] = list[i];
return array;
}
}
where T1
is a class and T2
is a struct. Both the class and struct members have Identical names and types. With the above I get red squigly in first method's list.Add(array[i])
and second methods array[i] = list[i]
so these don't work. What's the easiest way to do that?
EDIT
Here's the class:
public class PerSec : INotifyPropertyChanged
{
string yq;
float eps, nav, cash, debt;
public string YQ { get => yq; set { yq = value; OnPropertyChanged(); } }
public float EPS { get => eps; set { eps = value; OnPropertyChanged(); } }
public float NAV { get => nav; set { nav = value; OnPropertyChanged(); } }
public float Cash { get => cash; set { cash = value; OnPropertyChanged(); } }
public float Debt { get => debt; set { debt = value; OnPropertyChanged(); } }
#region Notify Property Changed Members
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string name = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
#endregion
}
and here's the struct:
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct PerSecStruct
{
//23 bytes
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)]
public string YQ;
public float EPS;
public float NAV;
public float Cash;
public float Debt;
}
EDIT
In second method, I've these now:
public static T2[] ListToarray<T1>(List<T1> list)
{
var structFields = typeof(PerSecStruct).GetFields(BindingFlags.Instance | BindingFlags.Public);
var classFields = typeof(PerSec).GetProperties(BindingFlags.Instance | BindingFlags.Public);
classFields = classFields.Where(x => structFields.Select(y => y.Name).Contains(x.Name)).ToArray();
var fieldsDictionary = structFields.Zip(classFields, (k, v) => new { StructField = k, ClassField = v }).ToDictionary(x => x.StructField, x => x.ClassField);
var array = new T2[list.Count];
for (int i = 0; i < list.Count; i++)
{
var psStruct = array[i];
var psClass = list[i];
foreach (var entry in fieldsDictionary)
{
var value = entry.Value.GetValue(psClass);
entry.Key.SetValue(psStruct, value);
}
}
return array;
}
this entry.Key.SetValue(psStruct, value);
line isn't working so the elements of array have their default values (null/0).
EDIT
It works if I use __makeref(array[i])
as noted here by petelids. With that I can do this:
public static T2[] ListToarray<T1>(List<T1> list)
{
var fields = typeof(T2).GetFields();
var properties = typeof(T1).GetProperties();
var array = new T2[list.Count];
for (int i = 0; i < list.Count; i++)
{
foreach (var field in fields)
{
var value = properties.First(x => x.Name == field.Name).GetValue(list[i]);
field.SetValueDirect(__makeref(array[i]), value);
}
}
return array;
}
I don't need those Binding Flags! And to convert back to List I've to do this in other method:
public static List<T1> ArrayToList<T1>(T2[] array) where T1 : new()
{
var fields = typeof(T2).GetFields();
var properties = typeof(T1).GetProperties();
var list = new List<T1>(array.Length);
for (int i = 0; i < array.Length; i++)
{
var obj = new T1();
foreach (var property in properties)
{
var value = fields.First(x => x.Name == property.Name).GetValue(array[i]);
property.SetValue(obj, value);
}
list.Add(obj);
}
return list;
}