powered by simpleCommunicator - 2.0.58     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Вызов GetType()
14 сообщений из 14, страница 1 из 1
Вызов GetType()
    #38036999
Lamo2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Читал тут одну книжку и в ней наткнулся на такой код

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
public abstract class Entity<TId>
{
    public virtual TId Id { get; protected set; }
    public override bool Equals(object obj)
    {
        return Equals(obj as Entity<TId>);
    }

    private static bool IsTransient(Entity<TId> obj)
    {
        return obj != null &&
        Equals(obj.Id, default(TId));
    }

    private Type GetUnproxiedType()
    {
        return GetType();
    }

    public virtual bool Equals(Entity<TId> other)
    {
        if (other == null)
            return false;
        if (ReferenceEquals(this, other))
            return true;
        if (!IsTransient(this) &&
        !IsTransient(other) &&
        Equals(Id, other.Id))
        {
            var otherType = other.GetUnproxiedType();
            var thisType = GetUnproxiedType();
            return thisType.IsAssignableFrom(otherType) ||
            otherType.IsAssignableFrom(thisType);
        }
        return false;
    }

    public override int GetHashCode()
    {
        if (Equals(Id, default(TId)))
            return base.GetHashCode();
        return Id.GetHashCode();
    }
}

public abstract class Entity : Entity<Guid>
{
}



Хотел узнать, а зачем вызов GetUnproxiedType() в Equals? Почему нельзя было просто вызвать other.GetType() и this.GetType()?
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037170
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Книжку писал пьяный песатель, видимо. Что за чтиво-то?
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037187
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУКнижку писал пьяный песатель, видимо. Что за чтиво-то?
Сам ты пьяный писатель, но в книжке тоже есть ошибка. Книжка NHibernate CookBook .

Lamo2012Хотел узнать, а зачем вызов GetUnproxiedType() в Equals? Почему нельзя было просто вызвать other.GetType() и this.GetType()?
Дело в том, что NHibernate делает динамические прокси классы, которые наследуют от классов доменной модели. Если вызвать на таком класси GetType(), то это будет не ваш класс, а класс с названием ProxyМногобукв. При этом внутри этого прокси-класса есть ссылка на настоящий класс.
Чтобы сравнить реальные типы и нужен GetUnproxiedType, только он должен быть с модификатором Protected или public. Волшество в том, что при таком раскладе проки-тип перенапривит вызов реальному типу, и вернёт его тип. Но для private методов такое волшебство не работает, т.к. они не переопределятеся прокси-типом. Поэтому private GetUnproxiedType() вернёт ProxyМногобукв, а public или protected GetUnproxiedType() вернёт тип доменной модели.
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037203
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtor, только пьяный архитектор может шунтировать классы подобными костылями.
((INHibernateProxy)proxy).HibernateLazyInitializer.PersistentClass тебе в помощь.
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037209
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУ,

отличии от твоего это 100% рабочий способ, не говоря уже о простоте. Ибо ((INHibernateProxy)proxy).HibernateLazyInitializer.PersistentClass будеть падать с InvalidCastException на свежесозданных Transient сущностях.
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037222
Фотография МСУ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtor, то, что этот гавнокод работает еще не означает, что подобный подход правильный. Недокументированные приемы - зло. Кстати, туда же: HibernateLazyInitializer.GetImplementation()
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037226
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SolYUtor,
Немного офтопа, а как Ваше мнение, на сегодняшний момент, можно бы было уйти от прокси, а маркировать реальные объекты, для кеширования, обновления из кеша и тд,?, поднялось бы быстродействие, была бы более изящное решение?
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037384
Lamo2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtorДело в том, что NHibernate делает динамические прокси классы, которые наследуют от классов доменной модели. Если вызвать на таком класси GetType(), то это будет не ваш класс, а класс с названием ProxyМногобукв.
Ну собственно это в книжке и написано.

SolYUtorПри этом внутри этого прокси-класса есть ссылка на настоящий класс.
Возможно. Но откуда методу GetUnproxiedType() об этом знать и как он вызовет GetType() у этого настоящего класса, если его реализация, описанная в книжке есть this.GetType()?

SolYUtorЧтобы сравнить реальные типы и нужен GetUnproxiedType, только он должен быть с модификатором Protected или public. Волшество в том, что при таком раскладе проки-тип перенапривит вызов реальному типу, и вернёт его тип. Но для private методов такое волшебство не работает, т.к. они не переопределятеся прокси-типом. Поэтому private GetUnproxiedType() вернёт ProxyМногобукв, а public или protected GetUnproxiedType() вернёт тип доменной модели.
Вот тут у меня почему-то стойкое убеждение что реализация Object.GetType() вернет именно "Точный тип текущего экземпляра в среде выполнения", а не что-то иное, т.е. в каком бы из родительских для прокси-класса метод описан не был, все равно будет возвращен именно тот тип, который создавался средой выполнения, а именно ПроксиЧегоТо. Правильно ли я думаю?
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037397
Фотография Алексей К
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
МСУSolYUtor, только пьяный архитектор может шунтировать классы подобными костылями.
((INHibernateProxy)proxy).HibernateLazyInitializer.PersistentClass тебе в помощь.Ужас какой. :-) Для сравнения, в EF это решается, на мой взгляд, более элегантно:
Код: c#
1.
var realEntityType = ObjectContext.GetObjectType(myEntity.GetType())
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037483
Lamo2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtor,

Сейчас для меня иерархия классов, строящаяся на основе описанного в книжке базового типа при работе NH представляется вот так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
using System;

namespace ConsoleApplication22
{
    class Program
    {
        static void Main(string[] args)
        {
            var v = new Proxy();
            var v2 = new Proxy();
            v.Equals(v2);
            Console.ReadKey();
        }
    }

    abstract class Entity
    {
        private Type GetUnproxiedType()
        { return GetType(); }

        public override bool Equals(object o)
        {
            var other = o as Entity;

            Console.WriteLine(other.GetType());
            Console.WriteLine(other.GetUnproxiedType());

            return true;
        }
    }

    class Product : Entity
    {
    }

    class Proxy : Product
    {
    }
}



И я не понимаю, почему private Type GetUnproxiedType() { return GetType(); } должен возвращать тип, в котором он описан, и уж тем более именно тип предка прокси, а не сам тип прокси?
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037524
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lamo2012И я не понимаю, почему private Type GetUnproxiedType() { return GetType(); } должен возвращать тип, в котором он описан, и уж тем более именно тип предка прокси, а не сам тип прокси?
Вы невнимательно читали. Есть класса А, и хибер вернул вам ПроксиА. ПроксиА содержит ссылку на А, и GetUproxiedType вызовет GetUnproxiedType на экземпляре А, но не ПроксиА, при условии, что GetUnproxiedType public | protected virtual. Просто GetType вызовется на экземпляре ПроксиА, и вернёт тип прокси.
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037535
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Lamo2012, аналогия грубая, но принцип такой.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
public class A
{
    public virtual Type GetUnproxiedType()
    {
       return GetType();
    }
}

public class ProxyA
{
    public ProxyA(A a)
    {
        this.a = a;
    }
    public virtual Type GetUnproxiedType()
    {
        return a.GetUproxiedType();
    }
}
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037539
SolYUtor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Забыл наследования добавить.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
public class A
{
    public virtual Type GetUnproxiedType()
    {
       return GetType();
    }
}

public class ProxyA : A
{
    public ProxyA(A a)
    {
        this.a = a;
    }
    public virtual Type GetUnproxiedType()
    {
        return a.GetUproxiedType();
    }
}
...
Рейтинг: 0 / 0
Вызов GetType()
    #38037559
Lamo2012
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SolYUtor,

Спасибо! Ваши ответы как всегда на высоте!

Я тут тоже нашел аналогичный ответ на этот вопрос.

Суть вот в чем
"I actually went ahead and wrote to the author of the book about this code. It turns out this is due to how the proxy wrapping works. Here is his response:

"If you don't understand how the proxy frameworks work, the idea can seem magical.

When NHibernate returns a proxy for the purposes of lazy loading, it returns a proxy instance inherited from the actual type. There are a few members we can access without forcing a load from the database. Among these are proxy's Id property or field, GetType(), and in some circumstances Equals() and GetHashCode(). Accessing any other member will force a load from the database.

When that happens, the proxy creates an internal instance. So, for example, a lazy loaded instance of Customer (CustomerProxy102987098721340978), when loaded, will internally create a new Customer instance with all of the data from the database. The proxy then does something like this:
Код: c#
1.
2.
3.
4.
5.
6.
7.
public overrides string Name 
{ 
    get { 
       return _loadedInstance.Name; 
    } 
    set { _loadedInstance.Name = value; } 
}



Incidentally, it's this overriding that requires everything to be virtual on entities that allow lazy loaded.

So, all calls to the Name property on the proxy are relayed to the internal Customer instance that has the actual data.

GetUnproxiedType() takes advantage of this. A simple call to GetType() on the proxy will return typeof(CustomerProxy02139487509812340); A call to GetUnproxiedType() will be relayed to the internal customer instance, and the internal customer instance will return typeof(Customer).""

Спасибо всем, кто откликнулся.
...
Рейтинг: 0 / 0
14 сообщений из 14, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Вызов GetType()
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]