То, как мы справляемся с этим, заключается в том, что все наши бизнес-классы наследуются от общего базового класса.
Общий базовый класс содержит установщик значения и получатель значения, которые используют отражение для установки и получения свойств в классе.Если запрошенное свойство отсутствует, и вызывающая сторона указывает, что это можно сделать, установщик добавляет значение в коллекцию пользовательских полей (UDF), которая аналогична вашим атрибутам.
Этот подходустраняет необходимость вызывающей стороны знать что-либо о том, как на самом деле хранятся значения (т. е. является ли оно обычным свойством в классе или в коллекции UDF) или даже о том, какой это тип данных.
Например, ваш код вызывающей стороны:
productX.Attributes[Price].SetValueFromString("95,3€");
в нашей системе будет:
productX.SetFieldValue("Price", "95,3€");
Мы широко используем это для взаимодействия с базой данных, связывания данных формы и т. Д.
Вот примеросновной метод установки:
public static void SetFieldValue(object oRecord, string sName, object oValue)
{
PropertyInfo theProperty = null;
FieldInfo theField = null;
System.Type oType = null;
try
{
oType = oRecord.GetType();
// See if the column is a property in the record
theProperty = oType.GetProperty(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public, null, null, new Type[0], null);
if (theProperty == null)
{
theField = oType.GetField(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
if (theField != null)
{
theField.SetValue(oRecord, Global.ValueFromDB(oValue, theField.FieldType.Name));
}
else
{
object[] aAttributes = null;
// See if the class type is decorated with the NoUDFs attribute. If so, do not add the attribute.
aAttributes = oType.GetCustomAttributes(typeof(NoUDFsAttribute), true);
if (aAttributes.Length == 0)
{
// Otherwise, anything that is not found as a property or a field will be stored as a UDF
oRecord.SetUDFValue(sName, oValue);
}
}
}
else
{
if (theProperty.CanWrite)
{
theProperty.SetValue(oRecord, Global.ValueFromDB(oValue, theProperty.PropertyType.Name), null);
}
}
}
catch (Exception theException)
{
// Handle the exception
}
}
И один из методов получения, где мы получаем значение в виде строки:
public static string GetFieldValueForSQL(object oRecord, string sName)
{
PropertyInfo theProperty = null;
FieldInfo theField = null;
System.Type oType = null;
try
{
oType = oRecord.GetType();
// See if the column is a property in the record
theProperty = oType.GetProperty(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public, null, null, new Type[0], null);
if (theProperty == null)
{
theField = oType.GetField(sName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
if (theField != null)
{
return Global.ValueForSQL(theField.GetValue(oRecord), theField.FieldType.Name);
}
else
{
UDF oUDF = null;
object[] aAttributes = null;
// See if the class type is decorated with the NoUDFs attribute. If so, do not get the value.
aAttributes = oType.GetCustomAttributes(typeof(NoUDFsAttribute), true);
if (aAttributes.Length == 0)
{
oUDF = oRecord.GetUDF(sName);
}
if (oUDF != null)
{
return Global.ValueForSQL(oUDF.Value);
}
else
{
return "Null";
}
}
}
else
{
return Global.ValueForSQL(theProperty.GetValue(oRecord, null), theProperty.PropertyType.Name);
}
}
catch (Exception theException)
{
// Handle the exception
return null;
}
}
Я оставил некоторые из внутренних вызовов метода, которые мыиспользуйте для приведения значений в соответствующий формат (ValueFromDB, ValueForSQL), чтобы вы могли видеть, как они используются, но их довольно просто реализовать.