Где и как можно вмешаться в создание обьекта (подсунуть вместо свеже созданого старый обьект)? А то интерфейсов много (IMapObjectFactory, IObjectFactory) а как этим воспользоваться не ясно...
Зарание спасибо.
... << RSDN@Home 1.2.0 alpha rev. 618>>
Здравствуйте, Дьяченко Александр, Вы писали:
ДА>Где и как можно вмешаться в создание обьекта (подсунуть вместо свеже созданого старый обьект)? А то интерфейсов много (IMapObjectFactory, IObjectFactory) а как этим воспользоваться не ясно...
Отрывок из несостоявшейся статьи:
MapDescriptor
Класс MapDescriptor является ключевым звеном в реализации механизмов маппинга и фактически представляет собой в некотором смысле расширение технологии Reflection, предлагая высокопроизводительные альтернативы наиболее медленным её частям.
В конце статьи мы рассмотрим несколько тестов, позволяющих оценить производительность библиотеки. А пока подробнее остановимся на самом классе MapDescriptor.
Класс MapDescriptor создаётся для каждого типа, в момент первого обращения к методу Map.Descriptor. Каждый раз во время маппинга библиотечные функции получают дескриптор класса и используют его для создания объектов и доступа к их полям и свойствам. Для каждого типа библиотека генерирует специальную версию класса, перекрывая определённые виртуальные методы, что позволяет добиваться приемлемой производительности.
Для создания объектов используется семейство методов CreateInstance(Ex).
Если взглянуть на исходный код методов CreateInstance, то можно обнаружить там использование Reflection. Это реализация методов по умолчанию, которая перекрывается для каждого типа специально сгенерированной для этой цели функцией.
Методы CreateInstanceEx введены в библиотеку специально для того, чтобы получить возможность управлять созданием объектов во время маппинга. По умолчанию эти методы обращаются к методам CreateInstance, но мы можем перехватить управление и получить контроль над созданием объектов.
Предположим, у нас имеются следующие таблицы для хранения информации о пациентах и докторах.
CREATE TABLE dbo.Person (
PersonID int NOT NULL PRIMARY KEY IDENTITY(1,1),
Name varchar(50)
) ON [PRIMARY]
CREATE TABLE dbo.Patient (
PatientID int NOT NULL PRIMARY KEY,
Birthday datetime
) ON [PRIMARY]
CREATE TABLE Doctor (
DoctorID int NOT NULL PRIMARY KEY,
Taxonomy varchar(50)
) ON [PRIMARY]
Таблица Person содержит информацию, которая является общей как для пациентов, так и для докторов и в модели классов должна быть представлена базовым классом Person:
public class Person
{
[MapField("PersonID")]
public int ID;
public string Name;
}
public class Patient : Person
{
public DateTime Birthday;
}
public class Doctor : Person
{
public string Taxonomy;
}
Наша задача – научится создавать объект правильного типа в зависимости от того, к какому типу относиться запись в результирующем рекордсете.
Рассмотрим следующий пример:
class PersonObjectFactory : IMapObjectFactory
{
public object CreateInstance(MapInitializingData data)
{
object o =
data.DataSource.GetFieldValue("PatientID", data.SourceData);
if (!(o is DBNull))
{
data.MapDescriptor = Map.Descriptor(typeof(Patient));
return data.MapDescriptor.CreateInstanceEx(data);
}
o = data.DataSource.GetFieldValue("DoctorID", data.SourceData);
if (!(o is DBNull))
{
data.MapDescriptor = Map.Descriptor(typeof(Doctor));
return data.MapDescriptor.CreateInstanceEx(data);
}
return Map.CreateInstance(typeof(Person));
}
}
class Program
{
static void Main(string[] args)
{
Map.Descriptor<Person>().ObjectFactory = new PersonObjectFactory();
using (DbManager db = new DbManager())
{
List<Person> list = db
.SetCommand(@"
SELECT
ps.*,
pt.*,
dt.*
FROM
Person ps
LEFT JOIN Patient pt ON pt.PatientID = ps.PersonID
LEFT JOIN Doctor dt ON dt.DoctorID = ps.PersonID")
.ExecuteList<Person>();
foreach (Person p in list)
{
Console.WriteLine("{0}", p.GetType().Name);
MapDescriptor md = Map.Descriptor(p.GetType());
foreach (IMemberMapper mm in md)
Console.WriteLine("{0}: {1}", mm.Name, mm.GetValue(p));
}
}
}
}
Если у нас имеется по одной записи в таблицах Patient и Doctor, то результат выполнения программы может быть следующим.
Patient
Birthday: 10/10/2000 12:00:00 AM
PersonID: 1
Name: Name 1
Doctor
Taxonomy: Physician
PersonID: 2
Name: Name 2
Класс PersonObjectFactory, использующийся в данном примере должен быть зарегистрирован как фабрика объектов где-нибудь в начале выполнения программы. После этого любой вызов CreateInstanceEx будет передавать управление методу CreateInstance интерфейса IMapObjectFactory. Обратите внимание на то, что если этот метод создаёт объект отличный от базового, то в параметре MapInitializingData переписывается поле MapDescriptor, для того чтобы обеспечить правильную работу маппинга нового объекта.
Фабрика объектов так же может быть полезна, если логика программы требует наличия всегда только одной копии конкретного объекта в памяти программы. В этом случае для уже существующих объектов метод IMapObjectFactory.CreateInstance может вернуть копию объекта из кеша.
Для доступа к источнику данных используется всё тот же параметр MapInitializingData. В принципе, вполне возможно реализовать свой механизм маппинга и установив свойство MapInitializingData.StopMapping в false сообщить библиотеке, что маппинг выполнять не нужно.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Дьяченко Александр, Вы писали:
ДА>>Где и как можно вмешаться в создание обьекта (подсунуть вместо свеже созданого старый обьект)? А то интерфейсов много (IMapObjectFactory, IObjectFactory) а как этим воспользоваться не ясно...
[Покусано]
IT>Класс PersonObjectFactory, использующийся в данном примере должен быть зарегистрирован как фабрика объектов где-нибудь в начале выполнения программы.
[Покусано]
Вот как раз как его зарегистрировать и не ясно. С остальным и по исходникам более или менее разобрался.
Судя по отрывку статья должна быть очень информативной. Вроде вопрос о том что бы ее куда-нибуть выложить подымался, но так ничего и не решили... А жаль... Может все таки куданить выложить то что есть?
Присоединяюсь, судя по отрывку статья должна быть очень интересной, содержательной и самое главное очень полезной. Было бы очень здорово если можно было ознакомится с ней.
Спасибо
Здравствуйте, Дьяченко Александр, Вы писали:
ДА>Вот как раз как его зарегистрировать и не ясно. С остальным и по исходникам более или менее разобрался.
Можно попробовать в статическом конструкторе самого класса.
... << RSDN@Home 1.2.0 alpha rev. 0>>
ДА>>Где и как можно вмешаться в создание обьекта (подсунуть вместо свеже созданого старый обьект)? А то интерфейсов много (IMapObjectFactory, IObjectFactory) а как этим воспользоваться не ясно...
IT>Отрывок из несостоявшейся статьи:
А можно надеяться на публикацию статьи в следующих номерах RSDN Magazine?
... << RSDN@Home 1.1.4 beta 7 rev. 467>> :: silent
Здравствуйте, Andre, Вы писали:
A>А можно надеяться на публикацию статьи в следующих номерах RSDN Magazine?
Я сейчас усиленно занимаюсь новой версий RFD, где всё будет ещё круче

так что даже не знаю, стоит ли пускать в журнал статью по версии, которая к выходу журнала уже будет не актуальна.
... << RSDN@Home 1.2.0 alpha rev. 0>>