У меня есть DAL, который обращается к нескольким файлам CSV, которые постоянно обновляют свои форматы и постоянно добавляют новые форматы.
каждая строка в CSV-файле представляет класс в системе, но из-за множества форматов ввод обрабатывается с помощью двухэтапного процесса.
Шаг 1. Преобразуйте строку из файла CSV в список значений. Преобразуйте этот список значений в «сырой» объект.
Этот необработанный объект затем будет отображен в объект бизнес-логики позже, поэтому все необработанные объекты будут преобразованы в объекты бизнес-логики.
Однако, поскольку некоторые из строк csv в значительной степени склоняются к созданию класса с вложенными классами, мой универсальный картограф на данный момент менее чем полезен.
Объект сопоставления - это атрибут с индексной позицией полей значений, присвоенный атрибутом свойства.
public static T BuildRawObject(string[] values)
{
T target = (T) Activator.CreateInstance(typeof(T), new object[] { });
Type targetInfo = target.GetType();
foreach (PropertyInfo pi in targetInfo.GetProperties())
{
if (!pi.PropertyType.IsValueType)
{
if (pi.PropertyType.IsAssignableFrom(typeof(NestedObj1)))
{
var result = BuildRawObject2<NestedObj1>(values);
try
{
pi.SetValue(target, Convert.ChangeType(result, pi.PropertyType));
}
catch (Exception e)
{
Console.WriteLine("Exception on property: " + pi.PropertyType +
" was bit not to set built instance on property. Instace was: " + result);
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
else if(pi.PropertyType.IsAssignableFrom(typeof(NestedObj2)))
{
var result = BuildRawObject2<NestedObj2>(values);
try
{
pi.SetValue(target, Convert.ChangeType(result, pi.PropertyType));
}
catch (Exception e)
{
Console.WriteLine("Exception on property: " + pi.PropertyType +
" was bit not to set built instance on property. Instace was: " + result);
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
else if (pi.PropertyType.IsAssignableFrom(typeof(NestedObj3)))
{
var result = BuildRawObject2<NestedObj3>(values);
try
{
pi.SetValue(target, Convert.ChangeType(result, pi.PropertyType));
}
catch (Exception e)
{
Console.WriteLine("Exception on property: " + pi.PropertyType +
" was bit not to set built instance on property. Instace was: " + result);
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
else if (pi.PropertyType.IsAssignableFrom(typeof(NestedObj5)))
{
var result = BuildRawObject2<NestedObj5>(values);
try
{
pi.SetValue(target, Convert.ChangeType(result, pi.PropertyType));
}
catch (Exception e)
{
Console.WriteLine("Exception on property: " + pi.PropertyType +
" was bit not to set built instance on property. Instace was: " + result);
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
else if (pi.PropertyType.IsAssignableFrom(typeof(NestedObj6)))
{
var result = BuildRawObject2<NestedObj6>(values);
try
{
pi.SetValue(target, result);
}
catch (Exception e)
{
Console.WriteLine("Exception on property: " + pi.PropertyType +
" was bit not to set built instance on property. Instace was: " + result);
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
else if (pi.PropertyType.IsAssignableFrom(typeof(NestedObj7)))
{
var result = BuildRawObject2<NestedObj7>(values);
try
{
pi.SetValue(target, Convert.ChangeType(result, pi.PropertyType));
}
catch (Exception e)
{
Console.WriteLine("Exception on property: " + pi.PropertyType +
" was bit not to set built instance on property. Instace was: " + result);
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
else
{
Console.WriteLine("An unrecognized class exists in the raw object. This will not be mapped to: " + pi.Name);
}
}
else
{
Mapping mapping = pi.GetCustomAttribute<Mapping>();
if (mapping != null)
{
values[mapping.SourceIndex] = EmptyStringValuesWhenEmpty(values[mapping.SourceIndex]);
if (pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?))
{
bool valid = DateTime.TryParse(values[mapping.SourceIndex], out DateTime dateTime);
if (valid)
{
pi.SetValue(target, dateTime, null);
}
else
{
Console.WriteLine("Value: " + values[mapping.SourceIndex] + " on position[" +
mapping.SourceIndex + "] was not a valid date time. Value is required.");
}
}
else
{
try
{
pi.SetValue(target, GenericConverter(values[mapping.SourceIndex], pi.PropertyType), null);
}
catch (Exception e)
{
Console.WriteLine("Exception on index: " + mapping.SourceIndex + " contained value: " +
values[mapping.SourceIndex] + " was attempted for property type: " +
pi.PropertyType +
"Parse was not possible. Either input file is in wrong format, or RawInputObject has incorect property");
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
}
else
{
Console.WriteLine("Mapping to field: " + pi.Name +
" was skipped due to missing mapping attribute definition.");
}
}
}
return target;
}
Проблема возникает, когда я пытаюсь присвоить значения вложенным классам для «Необработанного возвращаемого объекта».
в идеале я бы предпочел сделать все это рекурсивным методом. Однако родительский класс не того же типа, что и вложенные классы. Поэтому мне нужно создать новый метод, который делает то же самое, что и родительский класс, но принимает вложенные классы.
Однако создание, теоретически, бесконечного списка объектов именованного типа, которые могут встречаться в универсальном методе, просто ... неправильно. Я бы предпочел просто позволить программе сделать вывод из любого специализированного вложенного класса, переданного методу, чтобы определить, каким будет тип возвращаемого значения метода. Это возможно? Я не могу понять как.
Если я не совсем понимаю свой вопрос или у вас есть предложения, как я мог бы задать вопрос лучше, дайте мне знать. Если подробности отсутствуют. Пожалуйста, посоветуйте, и я дам.
Изменить: метод после предоставления решения
public static object BuildRawObject(Type objectType, string[] values)
{
dynamic target = Activator.CreateInstance(objectType, new object[] { });
Type targetInfo = target.GetType();
foreach (PropertyInfo pi in targetInfo.GetProperties())
{
if (pi.PropertyType.GetInterfaces().AsEnumerable().Contains(typeof(IRawObjectBase)) || pi.PropertyType.GetInterfaces().AsEnumerable().Contains(typeof(IRawNestedObjectBase)))
{
var result = BuildRawObject(pi.PropertyType, values);
try
{
pi.SetValue(target, Convert.ChangeType(result, pi.PropertyType));
}
catch (Exception e)
{
Console.WriteLine("Exception on property: " + pi.PropertyType +
" was bit not to set built instance on property. Instace was: " + result);
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
else
{
Mapping mapping = pi.GetCustomAttribute<Mapping>();
if (mapping != null)
{
values[mapping.SourceIndex] = EmptyStringValuesWhenEmpty(values[mapping.SourceIndex]);
if (pi.PropertyType == typeof(DateTime) || pi.PropertyType == typeof(DateTime?))
{
bool valid = DateTime.TryParse(values[mapping.SourceIndex], out DateTime dateTime);
if (valid)
{
pi.SetValue(target, dateTime, null);
}
else
{
Console.WriteLine("Value: " + values[mapping.SourceIndex] + " on position[" +
mapping.SourceIndex + "] was not a valid date time. Value is required.");
}
}
else
{
try
{
pi.SetValue(target, GenericConverter(values[mapping.SourceIndex], pi.PropertyType), null);
}
catch (Exception e)
{
Console.WriteLine("Exception on index: " + mapping.SourceIndex + " contained value: " +
values[mapping.SourceIndex] + " was attempted for property type: " +
pi.PropertyType +
"Parse was not possible. Either input file is in wrong format, or RawInputObject has incorect property");
Console.WriteLine("Exception mesessage was: " + e.Message);
if (e.InnerException != null)
{
Console.WriteLine("Inner Exception message was: " + e.InnerException.Message);
}
}
}
}
else
{
Console.WriteLine("Mapping to field: " + pi.Name +
" was skipped due to missing mapping attribute definition.");
}
}
}
return target;
}
static object BuildRawObject(Type objectType, string[] values)
, а потом сделатьBuildRawObject(pi.PropertyType, values)
? - person Evk   schedule 31.10.2017