Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 09.12.03 06:05
Оценка:
Всем привет.

На С++ это выглядит вот так:

class Control
{
protected:
    virtual void SomeMethod()
    {
        //Делает то, что нужно
    }
};

class SomeStandatdControl : public Control
{
protected:
    virtual void SomeMethod()
    {
        //Делает не то, что нужно
    }
};

class MyControl : public SomeStandatdControl
{
protected:
    virtual void SomeMethod()
    {
        //Вот тут вызов нужного метода через явную квалификацию
        Control::SomeMethod();
    }
};

А теперь вопрос, как такое написать на шарпе?

public class Control
{
    protected virtual void SomeMethod()
    {
        //Делает то, что нужно
    }
}

public class SomeStandatdControl : Control
{
    protected override void SomeMethod()
    {
        //Делает не то, что нужно
    }
}

public class MyControl : SomeStandatdControl
{
    protected override void SomeMethod()
    {
        //Как тут вызвать Control.SomeMethod???
        Control.SomeMethod(); // Error: Cannot access protected member 
        (this as Control).SomeMethod(); // Error: Cannot access protected member 
    }
}
Re: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 09.12.03 06:57
Оценка:
public class Control
{
    protected virtual void SomeMethod()
    {
        SomeMethodOfControl();
    }

    protected void SomeMethodOfControl()
    {
        //Делает то, что нужно
    }
}

public class SomeStandatdControl : Control
{
    protected override void SomeMethod()
    {
        //Делает не то, что нужно
    }
}

public class MyControl : SomeStandatdControl
{
    protected override void SomeMethod()
    {
        //Как тут вызвать Control.SomeMethod???
        //Control.SomeMethod(); // Error: Cannot access protected member 
        //(this as Control).SomeMethod(); // Error: Cannot access protected member 
        SomeMethodOfControl();
    }
}


иначе никак.
для вызова предыдущего в цепочке: base.SomeMethod();
Re: Неужели на C# такое не сделать???
От: Воронков Василий Россия  
Дата: 09.12.03 07:35
Оценка: +1 -1
Надо пока не поздно написать в МС, может, в следующей версии добавят. :crush: Хотя ты первый, кому это понадобилось.

Тут проблема в том, что обычно такие вещи в диезе разруливаются путем приведения экземпляра нужному типу. Т.е. если есть экз. типа С (потомка В, который в свою очередь потомок А), то нужный метод вызывается путем приведения к типу А. Однако в данном случае это не помогает

Уроды, в общем.
Posted via RSDN NNTP Server 1.8 beta
Re[2]: Неужели на C# такое не сделать???
От: Dr_Sh0ck Беларусь  
Дата: 09.12.03 07:38
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Уроды, в общем.


Согласен. Кто мешал сделать что-либо наподобие:
base(className).classMember

Do not fake yourself ;)
ICQ#: 198114726
Re[3]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 09.12.03 07:49
Оценка: 7 (1) +1
Здравствуйте, Dr_Sh0ck, Вы писали:

Это вопрос-то скорее философский. Если разработчик базового класса сделал свою реализацию — зачем вам лезть дальше в дебри дерева наследования, чтобы вытащить что-то оттуда из самого нутре? Мало ли зачем он его перегрузил — может он там состояние объекта своего меняет? А вы хотите в обход его реализации пойти.

А если Вы сами разрабочик обоих классов — легко сделаете то что например я предлагал, если уж не хочется повторять реализацию.

D_S>Здравствуйте, Воронков Василий, Вы писали:


ВВ>>Уроды, в общем.


D_S>Согласен. Кто мешал сделать что-либо наподобие:

D_S>
D_S>base(className).classMember
D_S>

D_S>
Re[4]: Неужели на C# такое не сделать???
От: Dr_Sh0ck Беларусь  
Дата: 09.12.03 07:56
Оценка: :)
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Здравствуйте, Dr_Sh0ck, Вы писали:


АО>Это вопрос-то скорее философский.


Да фишка еще и в том, что философия склонна меняться. Особенно у известной всем конторы...
Do not fake yourself ;)
ICQ#: 198114726
Re[4]: Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 09.12.03 08:21
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Здравствуйте, Dr_Sh0ck, Вы писали:


АО>Это вопрос-то скорее философский. Если разработчик базового класса сделал свою реализацию — зачем вам лезть дальше в дебри дерева наследования, чтобы вытащить что-то оттуда из самого нутре? Мало ли зачем он его перегрузил — может он там состояние объекта своего меняет? А вы хотите в обход его реализации пойти.


Вот именно меняет. Только одна маленькая деталь, не своего объекта, а уже нашего общего. Могу же я у собственного объекта сам выбирать поведение. И это поведение уже на 80% реализовано в пред-базовом, а потом в базовом урезано. Да дело даже не в этом. В данной ситуации я не могу вызвать защищенный метод своего предка. Доступ к защищенным методам предка это мое законное право как наследника, а тут меня его лишают. Какого хрена? В чем тут логика или хотябы философия???
Re[5]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 09.12.03 08:26
Оценка: 2 (2) +1
Здравствуйте, IvanM, Вы писали:

IM>Здравствуйте, Алексей Одинцов, Вы писали:


АО>>Здравствуйте, Dr_Sh0ck, Вы писали:


АО>>Это вопрос-то скорее философский. Если разработчик базового класса сделал свою реализацию — зачем вам лезть дальше в дебри дерева наследования, чтобы вытащить что-то оттуда из самого нутре? Мало ли зачем он его перегрузил — может он там состояние объекта своего меняет? А вы хотите в обход его реализации пойти.


IM>Вот именно меняет. Только одна маленькая деталь, не своего объекта, а уже нашего общего. Могу же я у собственного объекта сам выбирать поведение. И это поведение уже на 80% реализовано в пред-базовом, а потом в базовом урезано. Да дело даже не в этом. В данной ситуации я не могу вызвать защищенный метод своего предка. Доступ к защищенным методам предка это мое законное право как наследника, а тут меня его лишают. Какого хрена? В чем тут логика или хотябы философия???


в том же, почему и некоторые члены вашего предка вам недоступны (are private). Разработчик вашего базового класса сделал свою реализацию, деталей которой вы не знаете. Если позволить вам исключить из работы его функциональность — его (и ваш) класс станет вести себя неправильно. Если вам очень хочется вызвать Control.SomeMethod() — унаследуйтесь напрямую от него и повторите реализацию так как вам нравится, либо уж используйте базовый класс таким какой он есть.

Если же вы сами разработчик всех трех классов — значит учитесь правильнее проектировать иерархии классов.
Re[6]: Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 09.12.03 09:30
Оценка: -1
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Здравствуйте, IvanM, Вы писали:


IM>>Здравствуйте, Алексей Одинцов, Вы писали:


АО>в том же, почему и некоторые члены вашего предка вам недоступны (are private). Разработчик вашего базового класса сделал свою реализацию, деталей которой вы не знаете. Если позволить вам исключить из работы его функциональность — его (и ваш) класс станет вести себя неправильно. Если вам очень хочется вызвать Control.SomeMethod() — унаследуйтесь напрямую от него и повторите реализацию так как вам нравится, либо уж используйте базовый класс таким какой он есть.


АО>Если же вы сами разработчик всех трех классов — значит учитесь правильнее проектировать иерархии классов.


Я не говорю здесь про private, это совершенно другое, о них не пишут в документации, их вобще нет. Раз уж дело дошло до обсуждения вопросов проектирования, то мое мнение — любое дублирование кода (кода предка в наследнике в частности) ведет к проблемам при последующей поддержке в целостном состоянии. И тут любая разумная возможность повторного использования кода — благо. В данном случае, IMHO, ситуация разумная. По поводу иерархии
1. Не всегда мы можем все спроектировать сами, иногда это уже сделали за нас.
2. Идеальные иерархии в реальной жизни попадаются не всегда.

А что касается "вести себя неправильно", откуда такая уверенность, что непременно все начнет вети себя неправильно? Точно так же можно запретить доступ к защищеннвм полям класса. А вдруг мы их изменим и все начнет вести себя неправильно? Это паранойя а не логика.
Re[7]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 09.12.03 13:15
Оценка:
реализация функции — её код — такая же private как и приватные члены класса. то, что вам доступно вызвать её не говорит о том, что вы можете делать предположения о её коде.

если вы сами проектируете иерархии — у вас есть выход.

если не сами — Вам придется следовать логике программиста создавшего для Вас базовый класс. Вам не нравится его логика — напишите свой класс со своей. Если это невозможно по каким-то причинам (например, вы вынуждены использовать его как базовый) — увы. придется выкручиваться.

Но логика в таком подходе есть. Не сказал бы что я её разделяю, но мне всего пару раз пришлось столкнуться с этим ограничичением, и не могу сказать что оно такое уж драконовское. В C# и шаблонов пока нет, ну и что теперь? Хотите писать как на C++ — пишите на C++. Или пишите в MS пусть сделают эту Вашу фичу. Я ей применение тоже найду, хоть пока и не считаю её такой уж нужной.
Re[8]: Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 09.12.03 14:14
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Но логика в таком подходе есть. Не сказал бы что я её разделяю, но мне всего пару раз пришлось столкнуться с этим ограничичением, и не могу сказать что оно такое уж драконовское. В C# и шаблонов пока нет, ну и что теперь? Хотите писать как на C++ — пишите на C++. Или пишите в MS пусть сделают эту Вашу фичу. Я ей применение тоже найду, хоть пока и не считаю её такой уж нужной.


Вобщем, понятна логика. Во первых, С++ это не C#, а во вторых, ООП это не то, что я о нем думаю. Но, в любом случае, спасибо за ответ!
Re[5]: Неужели на C# такое не сделать???
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 10.12.03 12:49
Оценка:
Здравствуйте, IvanM, Вы писали:

IM>Вот именно меняет. Только одна маленькая деталь, не своего объекта, а уже нашего общего. Могу же я у собственного объекта сам выбирать поведение. И это поведение уже на 80% реализовано в пред-базовом, а потом в базовом урезано. Да дело даже не в этом. В данной ситуации я не могу вызвать защищенный метод своего предка. Доступ к защищенным методам предка это мое законное право как наследника, а тут меня его лишают. Какого хрена? В чем тут логика или хотябы философия???


public class A
{
    private ArrayList _list;
    
    public A()
    {
        Init();
    }
    
    protected virtual void Init()
    {
        _list = new ArrayList();
    }
    
    public virtual void Add(object item)
    {
        _list.Add(item);
    }
}

public class B : A
{
    private ArrayList _list2;
    
    protected override void Init()
    {
        base.Init();
        _list2 = new ArrayList();
    }
    
    public override void Add(object item)
    {
        base.Add(item);
        _list2.Add(item);
    }
}

public class C
{
    protected override void Init()
    {
        ((B)this).Init();
    }
}

...

C c = new C();
c.Add(25); // Null reference exception
... << RSDN@Home 1.1.2 beta 2 >>
AVK Blog
Re[6]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 10.12.03 12:57
Оценка:
Здравствуйте, AndrewVK, Вы писали:

а к чему этот код?

у тому же он не компилится в 1.1
даже после добавления : B к объявлению класса C.

в чем Вы его компилиировали?
Re[7]: Неужели на C# такое не сделать???
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 10.12.03 13:11
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>а к чему этот код?


чем тут логика или хотябы философия???


АО>у тому же он не компилится в 1.1

АО>даже после добавления : B к объявлению класса C.

АО>в чем Вы его компилиировали?


Ни в чем. Понятно что вызов через голову невозможен. Это демонстрация проблем если бы такая возможность была.
... << RSDN@Home 1.1.2 beta 2 >>
AVK Blog
Re[8]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 10.12.03 13:22
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Ни в чем. Понятно что вызов через голову невозможен. Это демонстрация проблем если бы такая возможность была.


тогда надо ((A)this).Init(); т.к. ((B)this).Init(); это то же что и base.Init();

а то несколько непонятно что пытались продемонстрировать.
Re[9]: Неужели на C# такое не сделать???
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 10.12.03 13:51
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>тогда надо ((A)this).Init(); т.к. ((B)this).Init(); это то же что и base.Init();


Ну да
... << RSDN@Home 1.1.2 beta 2 >>
AVK Blog
Re: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 10.12.03 15:29
Оценка:
Здравствуйте, IvanM, Вы писали:

Попробуй через делегаты. В Delphi обычная практика через TMethod.
Через рефлектор или CreateDelegate найти адрес метода и вствить его в соответствующее поля делегата, а на место ссылки на объект this.
и солнце б утром не вставало, когда бы не было меня
Re[6]: Неужели на C# такое не сделать???
От: IvanM Россия  
Дата: 10.12.03 17:07
Оценка:
Здравствуйте, AndrewVK, Вы писали:

AVK>Здравствуйте, IvanM, Вы писали:


AVK>...


Да я уже все понял, просто С++ ная привычка, что все можно
Re[2]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 12:07
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Через рефлектор или CreateDelegate найти адрес метода и вствить его в соответствующее поля делегата, а на место ссылки на объект this.


Не выйдет.
Делегат — не адрес метода, он намертво с объектом-владельцем метода связан. А как раз-таки ссылку на "объект-дедушку" вычислить не получится. Боюсь, что в VTBL текущего обекта даже упоминания нет про "дедушкин" метод. Такое пройдет только со статическим методом или если "дед" сам такой делегат вернет.
Re[3]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 12:21
Оценка:
Здравствуйте, Dax, Вы писали:

Dax>Делегат — не адрес метода, он намертво с объектом-владельцем метода связан. А как раз-таки ссылку на "объект-дедушку" вычислить не получится. Боюсь, что в VTBL текущего обекта даже упоминания нет про "дедушкин" метод. Такое пройдет только со статическим методом или если "дед" сам такой делегат вернет.

Почему же, делегат как раз имеет списочную структуру типа TMethod. А вот как выдернуть ссылку на дедушкин метод это другая проблема. Если это не абстрактный класс или через неабстрактного наследника не перекрывающего этот метод адрес выдернуть метода выдернуть можно просто создав объект этого типа создать делегат с его методом и заменить ссылку на объект на this.
и солнце б утром не вставало, когда бы не было меня
Re[6]: Неужели на C# такое не сделать???
От: Воронков Василий Россия  
Дата: 11.12.03 12:24
Оценка: -1
Ну и что? Любой код может привести к ошибкам. Даже такой:

public class A
{
protected MyType Child;
}


public class B
{
public void DoSomething()
{
Child.DoIt(); // Null reference exception
}
}

И что, из-за этого надо запрещать protected?
Posted via RSDN NNTP Server 1.8 beta
Re[4]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 12:41
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Почему же, делегат как раз имеет списочную структуру типа TMethod. А вот как выдернуть ссылку на дедушкин метод это другая проблема. Если это не абстрактный класс или через неабстрактного наследника не перекрывающего этот метод адрес выдернуть метода выдернуть можно просто создав объект этого типа создать делегат с его методом и заменить ссылку на объект на this.


Чистой воды хак. К тому же со многими "если". Я имел ввиду стандартные("цивилизованные") средства.
Замечу, что такого рода действия могут очень огорчить GC.
Re[5]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 12:48
Оценка:
Здравствуйте, Dax, Вы писали:

Dax>Здравствуйте, Serginio1, Вы писали:


S>> Почему же, делегат как раз имеет списочную структуру типа TMethod. А вот как выдернуть ссылку на дедушкин метод это другая проблема. Если это не абстрактный класс или через неабстрактного наследника не перекрывающего этот метод адрес выдернуть метода выдернуть можно просто создав объект этого типа создать делегат с его методом и заменить ссылку на объект на this.


Dax>Чистой воды хак. К тому же со многими "если". Я имел ввиду стандартные("цивилизованные") средства.

Dax>Замечу, что такого рода действия могут очень огорчить GC.
Ну а что же остается делать. В Паскале и не на такое идут. А GC только дедушкин объект и не найдет.
Интересно а каким образом он огорчается???
и солнце б утром не вставало, когда бы не было меня
Re[7]: Неужели на C# такое не сделать???
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 11.12.03 12:51
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Ну и что? Любой код может привести к ошибкам. Даже такой:


В таком коде ты явно напоганил, а в моем примере ты вроде как ничего криминального не делал.
... << RSDN@Home 1.1.2 beta 2 >>
AVK Blog
Re[6]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 13:44
Оценка:
S> Ну а что же остается делать. В Паскале и не на такое идут. А GC только дедушкин объект и не найдет.

Дык из Паскаля из "нетакого" еще и сухим выйти можно. А тут у managed-делегата на _target memcopy предлагается.

private RuntimeMethodInfo _method;
private IntPtr _methodPtr;
private IntPtr _methodPtrAux;
private object _target; //- он самый



S>Интересно а каким образом он огорчается???

У него проблемы с памятью начинаются, в прямом смыле — жуткий склероз
А потом, плачет наверное, тихенько-тихенько
Re[7]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 11.12.03 13:48
Оценка:
Здравствуйте, Dax, Вы писали:

Dax>
Dax>private RuntimeMethodInfo _method;
Dax>private IntPtr _methodPtr;
Dax>private IntPtr _methodPtrAux;
Dax>private object _target; //- он самый
Dax>


чего это за обрезок кода?
Re[7]: Неужели на C# такое не сделать???
От: Yury_Malich Германия http://malich.ru
Дата: 11.12.03 13:51
Оценка:
Dax>У него проблемы с памятью начинаются, в прямом смыле — жуткий склероз
Dax>А потом, плачет наверное, тихенько-тихенько

IMO не будет с CG ничего страшного. При слудующей сборке мусора он наверное просто не найдёт ссылку на подменённый объект и его убъёт из кучи
"Практика — критерий истины" (c) Маркс
Re[8]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 13:52
Оценка:
Dax>>
Dax>>private RuntimeMethodInfo _method;
Dax>>private IntPtr _methodPtr;
Dax>>private IntPtr _methodPtrAux;
Dax>>private object _target; //- он самый
Dax>>


АО>чего это за обрезок кода?


немножко исходника System.Delegate, прошу прощения, забыл указать
Re[7]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 11.12.03 13:57
Оценка:
object Target { get; }

оно read-only. поэтому через делегат это провернуть не получится. только если в unsafe поменять напрямую в памяти указатели. только грязными хаками можно это сделать.
Re[7]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 13:57
Оценка:
Здравствуйте, Dax, Вы писали:

S>> Ну а что же остается делать. В Паскале и не на такое идут. А GC только дедушкин объект и не найдет.


Dax>Дык из Паскаля из "нетакого" еще и сухим выйти можно. А тут у managed-делегата на _target memcopy предлагается.


Dax>
Dax>private RuntimeMethodInfo _method;
Dax>private IntPtr _methodPtr;
Dax>private IntPtr _methodPtrAux;
Dax>private object _target; //- он самый
Dax>



S>>Интересно а каким образом он огорчается???

Dax>У него проблемы с памятью начинаются, в прямом смыле — жуткий склероз
Dax>А потом, плачет наверное, тихенько-тихенько

Сейчас уже не помню, но к _target напрямую обращались (сейчас Нет под рукой Net), но можно и через рефлексию его установить, тогда думаю GC будет веселее.
и солнце б утром не вставало, когда бы не было меня
Re[8]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 14:00
Оценка:
Y_M>IMO не будет с CG ничего страшного. При слудующей сборке мусора он наверное просто не найдёт ссылку на подменённый объект и его убъёт из кучи

Угу, а

private IntPtr _methodPtr;


куда будет указывать?
Re[8]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 14:02
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>object Target { get; }


АО>оно read-only. поэтому через делегат это провернуть не получится. только если в unsafe поменять напрямую в памяти указатели. только грязными хаками можно это сделать.

А через отображение через FldInfo ????
и солнце б утром не вставало, когда бы не было меня
Re[9]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 11.12.03 14:08
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> А через отображение через FldInfo ????


а кто вам его даст?
Re[9]: Неужели на C# такое не сделать???
От: Алексей Одинцов Россия  
Дата: 11.12.03 14:10
Оценка:
Здравствуйте, Dax, Вы писали:

Y_M>>IMO не будет с CG ничего страшного. При слудующей сборке мусора он наверное просто не найдёт ссылку на подменённый объект и его убъёт из кучи


Dax>Угу, а


Dax>
Dax>private IntPtr _methodPtr;
Dax>


Dax>куда будет указывать?


номер метода это. простой инт.
Re[10]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 14:21
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Здравствуйте, Serginio1, Вы писали:


S>> А через отображение через FldInfo ????


АО>а кто вам его даст?

А разве нет такого флага BindingFlags.Private ????
и солнце б утром не вставало, когда бы не было меня
Re[10]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 14:32
Оценка:
Здравствуйте, Алексей Одинцов, Вы писали:

АО>Здравствуйте, Serginio1, Вы писали:


S>> А через отображение через FldInfo ????


АО>а кто вам его даст?


Можно вообще эту проблему через отображение решить

mi=ТипДедушки.GetMethod("SomeMethod",BindingFlags.Protected | BindingFlags.Instance);
mi.Invoke(this,new object[]);
Просто через делегаты быстрее если ее часто использовать
http://www.rsdn.ru/Forum/?mid=395620
Автор: Serginio1
Дата: 29.09.03
и солнце б утром не вставало, когда бы не было меня
Re[11]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 14:36
Оценка:
S>Можно вообще эту проблему через отображение решить

S>mi=ТипДедушки.GetMethod("SomeMethod",BindingFlags.Protected | BindingFlags.Instance);

S> mi.Invoke(this,new object[]);
S> Просто через делегаты быстрее если ее часто использовать

Опять мимо.
В этом случае вызовется свой метод, а не деда. (к слову, нет такого BindingFlags.Protected есть BindingFlags.NonPublic)
Re[12]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 14:40
Оценка:
Здравствуйте, Dax, Вы писали:

S>>Можно вообще эту проблему через отображение решить


S>>mi=ТипДедушки.GetMethod("SomeMethod",BindingFlags.Protected | BindingFlags.Instance);

S>> mi.Invoke(this,new object[]);
S>> Просто через делегаты быстрее если ее часто использовать

Dax>Опять мимо.

Dax>В этом случае вызовется свой метод, а не деда. (к слову, нет такого BindingFlags.Protected есть BindingFlags.NonPublic)
А как через установку _target челез филдИнфо ????
и солнце б утром не вставало, когда бы не было меня
Re[12]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 14:42
Оценка:
Здравствуйте, Dax, Вы писали:

S>>Можно вообще эту проблему через отображение решить


S>>mi=ТипДедушки.GetMethod("SomeMethod",BindingFlags.Protected | BindingFlags.Instance);

S>> mi.Invoke(this,new object[]);
S>> Просто через делегаты быстрее если ее часто использовать

Dax>Опять мимо.

Dax>В этом случае вызовется свой метод, а не деда. (к слову, нет такого BindingFlags.Protected есть BindingFlags.NonPublic)

Считаешь, что mi вернет не прямой адрес, а ссылку на VMT ????
и солнце б утром не вставало, когда бы не было меня
Re[13]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 14:52
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Считаешь, что mi вернет не прямой адрес, а ссылку на VMT ????


Естественно, метод же виртуальный.

С FieldInfo тоже облом — не отдает .NET fieldInfo на _target.
Я ж говорю: по честному никак не получится, а хак, он и в Африке на следующей версии .NET прекратит работу.
Re[14]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 14:58
Оценка:
Здравствуйте, Dax, Вы писали:

Dax>Здравствуйте, Serginio1, Вы писали:


S>> Считаешь, что mi вернет не прямой адрес, а ссылку на VMT ????


Dax>Естественно, метод же виртуальный.


Dax>С FieldInfo тоже облом — не отдает .NET fieldInfo на _target.

Dax>Я ж говорю: по честному никак не получится, а хак, он и в Африке на следующей версии .NET прекратит работу.

Не должны быть еще хитрые методы. Извини, если не в лом посмотри из своих классов
можно ли через fieldInfo на приватные поля влиять. У меня сейчас Нет Net, а очень интересно.
и солнце б утром не вставало, когда бы не было меня
Re[15]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 15:05
Оценка:
S> Не должны быть еще хитрые методы. Извини, если не в лом посмотри из своих классов
S>можно ли через fieldInfo на приватные поля влиять. У меня сейчас Нет Net, а очень интересно.

На свои влиять можно (в смысле своих классов). А наследник от System.Delegate _target уже не видит.
Re[16]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 15:12
Оценка:
Здравствуйте, Dax, Вы писали:

S>> Не должны быть еще хитрые методы. Извини, если не в лом посмотри из своих классов

S>>можно ли через fieldInfo на приватные поля влиять. У меня сейчас Нет Net, а очень интересно.

Dax>На свои влиять можно (в смысле своих классов). А наследник от System.Delegate _target уже не видит.


Спасибо. Борцы хреновы. Унсейф . А через рефакторинг _target видно???
и солнце б утром не вставало, когда бы не было меня
Re[17]: Неужели на C# такое не сделать???
От: Dax  
Дата: 11.12.03 15:49
Оценка:
S> Спасибо. Борцы хреновы. Унсейф . А через рефакторинг _target видно???

Через reflection видно. Ты был на половину прав

Короче, _target меняется следющим образом:


//
public delegate void MethodDelegate();

//
A a = new A();
Delegate am = Delegate.CreateDelegate(typeof(MethodDelegate), a, "Method");

FieldInfo d = am.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance | BindingFlags.NonPublic);
d.SetValue(am, this);

am.DynamicInvoke(null);


самое смешное, что все нормально работает, _target меняется, но! вызывается свой же метод, а не "деда".
Re[18]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 16:06
Оценка:
Здравствуйте, Dax, Вы писали:

S>> Спасибо. Борцы хреновы. Унсейф . А через рефакторинг _target видно???


Dax>Через reflection видно. Ты был на половину прав


Dax>Короче, _target меняется следющим образом:


Dax>

Dax>//
Dax>public delegate void MethodDelegate();

Dax>//
Dax>A a = new A();
Dax>Delegate am = Delegate.CreateDelegate(typeof(MethodDelegate), a, "Method");

Dax>FieldInfo d = am.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance | BindingFlags.NonPublic);
Dax>d.SetValue(am, this);

Dax>am.DynamicInvoke(null);

Dax>


Dax>самое смешное, что все нормально работает, _target меняется, но! вызывается свой же метод, а не "деда".


А ты без DynamicInvoke
delegate void procedureWithOutParameters();

procedureWithOutParameters am=(procedureWithOutParameters) Delegate.CreateDelegate(typeof(procedureWithOutParameters),a,"Method");

FieldInfo d = am.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance | BindingFlags.NonPublic);
d.SetValue(am, this);

am();

http://www.rsdn.ru/Forum/Message.aspx?mid=395620&amp;only=1
Автор: Serginio1
Дата: 29.09.03
и солнце б утром не вставало, когда бы не было меня
Re[19]: Mожно. Но нужно ли?
От: Dax  
Дата: 11.12.03 16:26
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>А ты без DynamicInvoke


Без DynamicInvoke все ok. (c) Пушкин

Дед вызывается. Не знаю на сколько это функционально в пределах нормального приложения, но простые тесты показывают, что метод вызывается.
Re[20]: Mожно. Но нужно ли?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 16:36
Оценка:
Здравствуйте, Dax, Вы писали:

Слава Dax. Еще проще чем в Delphi.
Dax>Без DynamicInvoke все ok. (c) Пушкин

Dax>Дед вызывается. Не знаю на сколько это функционально в пределах нормального приложения, но простые тесты показывают, что метод вызывается.


А куда он денется. Делегату по барабану, что у него в полях содержится, тупо загоняет параметры и Call по адресу.
А при DynamicInvoke он уже отображение подключает и не работает на прямую.
и солнце б утром не вставало, когда бы не было меня
Re[20]: Mожно. Но нужно ли?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 16:37
Оценка:
Здравствуйте, Dax, Вы писали:

Dax>Здравствуйте, Serginio1, Вы писали:


S>>А ты без DynamicInvoke


Dax>Без DynamicInvoke все ok. (c) Пушкин


Dax>Дед вызывается. Не знаю на сколько это функционально в пределах нормального приложения, но простые тесты показывают, что метод вызывается.


Тыы бы полный код привел, а я тебе большую оценочку поставил.
и солнце б утром не вставало, когда бы не было меня
Re[21]: Mожно. Но нужно ли?
От: Dax  
Дата: 11.12.03 16:43
Оценка: 78 (7)
Здравствуйте, Serginio1, Вы писали:

S> Тыы бы полный код привел, а я тебе большую оценочку поставил.



using System;
using System.Reflection;

namespace ConsoleApplication1 {

    class Class1 {

        [STAThread]
        static void Main(string[] args) {
            new C().Test();
            Console.ReadLine();
        }
    }

    public delegate void MD();

    class A {
        protected virtual void M() {
            Console.WriteLine("A.M");
        }
    }

    class B:A {
        protected override void M() {
            Console.WriteLine("B.M");
        }
    }

    class C:B {
        protected override void M() {
            Console.WriteLine("C.M");
        }
        public void Test() {
            A a = new A();
            MD am = (MD)Delegate.CreateDelegate(typeof(MD), a, "M");
            am.GetType().BaseType.BaseType.GetField("_target", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(am, this);
            am();
        }

    }


}
Re[20]: Mожно. Но нужно ли?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 11.12.03 16:50
Оценка:
Здравствуйте, Dax, Вы писали:

Всякое бывает. Ради спортивного интереса.
Решение есть и на душе приятно. Всяко лучше чем конфигурирование в 1С
и солнце б утром не вставало, когда бы не было меня
Re[22]: Mожно. Но нужно ли?
От: Алексей Одинцов Россия  
Дата: 12.12.03 07:44
Оценка:
Здравствуйте, Dax, Вы писали:

прикололо — у меня в примере в точности те же названия функций и делегата только c BaseType.BaseType недотумкался взять.
Re[22]: Mожно. Но нужно ли?
От: IvanM Россия  
Дата: 12.12.03 14:41
Оценка:
Здравствуйте, Dax, Вы писали:

Dax>...


Офигенно! Чего только люди ни придумают
Re[4]: Неужели на C# такое не сделать???
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 05.01.04 11:08
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Dax, Вы писали:


Dax>>Здравствуйте, Serginio1, Вы писали:


S>>>Через рефлектор или CreateDelegate найти адрес метода и вствить его в соответствующее поля делегата, а на место ссылки на объект this.


Dax>>Не выйдет.

Dax>>Делегат — не адрес метода, он намертво с объектом-владельцем метода связан. А как раз-таки ссылку на "объект-дедушку" вычислить не получится. Боюсь, что в VTBL текущего обекта даже упоминания нет про "дедушкин" метод. Такое пройдет только со статическим методом или если "дед" сам такой делегат вернет.
S> Почему же, делегат как раз имеет списочную структуру типа TMethod. А вот как выдернуть ссылку на дедушкин метод это другая проблема. Если это не абстрактный класс или через неабстрактного наследника не перекрывающего этот метод адрес выдернуть метода выдернуть можно просто создав объект этого типа создать делегат с его методом и заменить ссылку на объект на this.

Кстати, через MethodInfo.MethodHandle.GetFunctionPointer(); можно вытащить любой метод типа и соответственно заполнив структур делегата все сделать и без создания дедушкиного объекта.
и солнце б утром не вставало, когда бы не было меня
Re[5]: Неужели на C# такое не сделать???
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 05.01.04 11:21
Оценка:
Кстати стоит удалять лишнее цитирование.
... << RSDN@Home 1.1.2 beta 2 >>
AVK Blog
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.