Есть классы, которые содержат в себе ссылки на объекты других классов, что-то типа:
class Classificator
{
int id;
string Title;
}
class SomeObject
{
int id;
string Title;
Classificator Type;
}
Загружать объекты в таком случае помогает реализация IMapSettable классом SomeObject
Хочется, чтобы при сохранении объектов (при создании параметров с помощью DbManager.CreateParameters(object source)) можно было также обойтись реализацией IMapGettable, в которой можно было бы переопределить метод GetField и внутри него можно было написать:
public bool GetField(string fieldName, out object value)
{
MapDescriptor md = MapDescriptor.GetDescriptor(this.GetType());
IMemberMapper mapper = md.GetMember(fieldName);
if (mapper != null && mapper.IsClass && mapper.MemberType.IsSubclassOf(typeof (Classificator)))
{
Classificator c = mapper.GetValue(this);
value = c.id;
return true;
}
return false;
}
Скажите пожалуйста, реализовано что-то подобное?
Может можно как-то по-другому? Подскажите пожалуйста, как?
Каковы шансы того, что если я напишу этот самый IMpaGettable, переделаю все места, где встречается IMapDataSource.GetFieldData и отдам автору исходники, подобный код попадет в основную ветку (а то merge-ить при новой версии не очень улыбается)?
Достаточно ли будет переписать в MapDescriptor методы GetFieldValue?
object IMapDataSource.GetFieldValue(int i, object entity)
{
IMemberMapper mm = (IMemberMapper)_memberList[i];
IMapGettable mg;
if ((mg = entity as IMapGettable) != null)
{
object value;
if (mg.GetField((this as IMapDataSource).GetFieldName(i), out value))
return value;
}
return mm.GetValue(entity);
}
object IMapDataSource.GetFieldValue(string name, object entity)
{
IMemberMapper mm = this[name];
IMapGettable mg;
if ((mg = entity as IMapGettable) != null)
{
// TODO : should mm be tested for null ?object value;
if (mg.GetField(name, out value))
return value;
}
return mm != null ? mm.GetValue(entity) : null;
}
и добавить
public interface IMapGettable
{
bool GetField(string fieldName, out object value);
}
?
Неудобно только то, что всем out параметрам нужно будет явно присваивать значение в реализации GetFieldstring fieldName, out object value).
Здравствуйте, oleksab, Вы писали:
O> Неудобно только то, что всем out параметрам нужно будет явно присваивать значение в реализации GetFieldstring fieldName, out object value).
Да уж, как-то это всё не очень... Я бы глянул в сторону конструктора с MapInitializeData параметром. Он перед маппингом получает в это структуре все необходимые данные.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
O>> Неудобно только то, что всем out параметрам нужно будет явно присваивать значение в реализации GetFieldstring fieldName, out object value).
IT>Да уж, как-то это всё не очень...
Не очень out? Его можно поменять на ref
Или сама идея вызывать IMapGettable.GetField в MapDescriptor.GetFieldValue плоха?
Можно переделать с ref как
object IMapDataSource.GetFieldValue(string name, object entity)
{
IMemberMapper mm = this[name];
object value = mm != null ? mm.GetValue(entity) : null;
IMapGettable mg;
if ((mg = entity as IMapGettable) != null && value != null)
{
mg.GetField(name, ref value);
}
return value;
}
Тогда IMapGettable.GetField если захочет — изменит значение value. Ну а если нет — то нет.
IT>Я бы глянул в сторону конструктора с MapInitializeData параметром. Он перед маппингом получает в это структуре все необходимые данные.
Это в смысле Map.MapInternal? Но там проверку на реализацию IMapGettable прийдется делать в двух местах:
Map.MapInternal(
IMapDataSource source,
object sourceData,
IMapDataReceiver receiver,
object receiverData,
MapInitializingData data)
{
if (receiverData is ISupportInitialize)
((ISupportInitialize)receiverData).BeginInit();
// реализует ли sourceData IMapGettable
IMapGettable mg = sourceData as IMapGettable;
if (receiverData is IMapSettable)
{
IMapSettable mapReceiver = (IMapSettable)receiverData;
for (int i = 0; i < source.FieldCount; i++)
{
string name = source.GetFieldName(i);
object o = source.GetFieldValue(i, sourceData);
// проверка №1 if (mg != null)
{
// скажем для какого поля будет подставлено значение
mg.GetField(name, ref o);
}
MapDescriptor md = data.MapDescriptor;
if (mapReceiver.SetField(name, o) == false)
{
int idx = receiver.GetOrdinal(name);
if (idx >= 0)
{
receiver.SetFieldValue(idx, name, receiverData, o);
}
}
}
}
else
{
for (int i = 0; i < source.FieldCount; i++)
{
string name = source.GetFieldName(i);
// -----------------------------------if (name.Length > 0)
{
int idx = receiver.GetOrdinal(name);
if (idx >= 0)
{
object o = source.GetFieldValue(i, sourceData);
// проверка №2if (mg != null)
{
// скажем для какого поля будет подставлено значение
mg.GetField(name, ref o);
}
receiver.SetFieldValue(idx, name, receiverData, o);
}
}
}
}
if (receiverData is ISupportInitialize)
((ISupportInitialize)receiverData).EndInit();
}