Изменить метод класса C # во время выполнения - PullRequest
2 голосов
/ 14 апреля 2009

Я бы хотел переопределить метод класса, не наследуя базовый класс, потому что это заняло бы много времени и изменений, а следовательно, все больше и больше тестов. Это так:

class TestClass{
    public void initialMethod(){
        ...
    }
}

И где-нибудь в коде я хотел бы сделать что-то вроде этого:

public testMethod()
{
    return;
}
test(){
    changeMethod(TestClass.initialMethod, testMethod);
}

И эта функция changeMethod переопределяет initialMethod TestClass, чтобы вместо этого она вызывала testMethod.

Наследование и переопределение метода с использованием обычных практик не является опцией, так как этот класс A является графическим компонентом, и при его инсертировании (и изменении) будет разбито много кода.

Редактировать: у нас нет базового кода для TestClass, поэтому нельзя изменить код, определяющий initialMethod в качестве делегата.

Редактировать 2: Поскольку это графический компонент, дизайнер автоматически добавил много кода. Если бы я унаследовал этот код, мне пришлось бы заменить весь код, добавленный дизайнером. Вот почему я не хотел бы заменять этот компонент.

Ответы [ 6 ]

7 голосов
/ 14 апреля 2009

Вам нужен шаблон Стратегия .

Основные шаги:

  • Создать интерфейс с ie. Do () подпись
  • Ваш initialMethod () должен вызывать стратегию . Do () , где стратегия - это тип вашего интерфейса
  • Создайте класс, который реализует этот интерфейс. Do () теперь ваш метод испытаний.
  • Добавьте в ваш основной класс экземпляр этого класса

Если работа не такая большая (скажем, просто замена цвета или еще что-то), то я согласен с решением Джонни Д. Кано с делегатом C # (анонимный) s.

Редактировать (после редактирования 2)

Май - как доказательство концепции - вы должны наследовать класс и заменить все ссылки из базового класса на этот новый. Делай это и ничего больше. Если это работает, вы можете подумать о следующих шагах (новые методы или делегаты и т. Д.)

Вам нужна только новая проверка из вашей системы контроля версий, и, если она может потерпеть неудачу, вы можете отказаться от нее. Стоит попробовать.

3 голосов
/ 14 апреля 2009

Возможно, вы можете сделать это как делегат.

class TestClass {
    public Action myAction;
    public void initialMethod(){
        ...
    }

    initialMethod

    public TestClass() {
        myAction = initialMethod;
    }
}

и затем на TestMethod

public testMethod()
{
    return;
}
test() {
    testClassInstance.myAction = testMethod;
}
2 голосов
/ 14 апреля 2009

Я думаю, что вам лучше всего использовать AOP-фреймворк, такой как LinFu. Там есть статья, в которой рассказывается о проекте codeproject:

Знакомство с LinFu, часть VI: LinFu.AOP - перехват и замена распространенного метода для закрытых типов на любом языке .NET

0 голосов
/ 14 апреля 2009

Короткий и простой ответ: если вы не можете настроить базовый код TestClass, нет, вы не можете изменить класс, чтобы заменить метод другим. Как только мы начинаем делать такие вещи, мы переходим на совершенно другой язык, такой как JavaScript.

Более длинный ответ: это зависит от того, кто вызывает замененный метод.

Если это другие классы, посмотрите, не можете ли вы реализовать Proxy между ними и немодифицируемым конкретным классом. То, выполнимо ли это, зависит от того, реализует ли этот класс интерфейсы или является его собственным интерфейсом.

Если это сам класс, то единственный вариант - декомпилировать и модифицировать класс во время разработки, используя Reflector (или эквивалентные инструменты), или во время выполнения, используя Reflection.Emit. Однако, чтобы идти по этому пути, вам должно быть очень больно, потому что он наверняка будет болезненным и ломким.

К сожалению, вы до сих пор не объяснили, что вы пытаетесь сделать и почему. Замена методов на ходу - это мощная штука в языках, которые позволяют это делать напрямую ... Могут быть библиотеки-насмешки, которые можно скрутить достаточно далеко, чтобы выполнять рефлексию, но тогда вы будете кататься на коньках по тонкому льду.

0 голосов
/ 14 апреля 2009

Если у вас нет кода, используйте методы расширения.

public void doSmth(this objectYOUWANT arg)
{
   //Do Something
}

Здесь вы используете принцип Закрыто для модификации Открыто для расширения.

Это добавит функциональность в библиотеку, у которой нет исходного кода. Это очень чисто сделать так.

Издание:

В FrameWork 3.5 есть что-то новое, называемое методами расширения. Подобные методы добавляют функциональность к закрытой сборке, позволяя вам расширить функциональность закрытой dll / сборки.

Чтобы использовать это, например, у вас есть импортируемая вами dll, которая называется Graphics.dll (у вас есть ссылка на ваш проект)

Прежде всего вы должны создать новый статический класс, который называется, например, Extension:

public static class Extensions
{
}

Во-вторых, вы хотите добавить дополнительные функциональные возможности к классу, содержащемуся в Graphics.dll с именем ChartGraph. Вы сделаете это:

public static class Extensions
{
    public static void draw(this ChartGraph g)
    {
       // DO SOMETHING
    }
}

В-третьих, когда вы создаете экземпляр нового объекта из graphics.dll, теперь у вас будет новый созданный вами метод:

ChartGraph myG = new ChartGraph();
myG.draw();

Как вы видите, вы добавили новую функциональность без особых усилий без перекомпиляции dll, это хорошо, если у вас нет исходного кода.

0 голосов
/ 14 апреля 2009

Если «TestClass» - это то, что вы определили, вы можете заменить определение «initialMethod» свойством и делегатом, которые затем могут быть установлены для любого метода с данной сигнатурой. (Даже анонимные.)

class TestClass {
  Action _myMethod;
  Action MyMethod {
    get { return _myMethod; }
    set { _myMethod = value; }
}

var tc = new TestClass()
tc.MyMethod = () -> Console.WriteLine("Hello World!");
tc.MyMethod()

Приведенный выше код не проверен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...