2009-04-13 3 views
2

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

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

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

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

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

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

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

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

+0

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

+0

Второй вопрос Петра. Звучит так, как будто вы говорите о тестовом коде, но я не понимаю вашего комментария о замене всего кода, добавленного дизайнером. –

+0

Фрагменты кода сбивают с толку. Когда вы говорите TestClass, вы имеете в виду класс ', который содержит тесты' или класс 'для тестирования'? – Gishu

ответ

7

Вам нужен шаблон Strategy.

Основные этапы:

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

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

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

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

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

+0

Шаблон стратегии хорошо и хорошо сам по себе, но не помогает, если код базового класса не может быть изменен. –

+0

О да, я вижу «редактирование 2». – boj

0

Если «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() 

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

3

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

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

    initialMethod 

    public TestClass() { 
     myAction = initialMethod; 
    } 
} 

, а затем на TestMethod

public testMethod() 
{ 
    return; 
} 
test() { 
    testClassInstance.myAction = testMethod; 
} 
0

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

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

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

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

Издание:

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

Чтобы использовать это, например, у вас есть 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

Куда я могу добавить этот код? Не могли бы вы прояснить это немного больше? – Rodrigo

+1

, который добавит только новый метод, а не переопределяет реализацию существующего метода. –

+0

Он не хочет переопределять метод Эриха ... прочитайте его вопрос. С наилучшими пожеланиями! – MRFerocius

0

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

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

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

Если это сам класс, то единственным вариантом является декомпиляция и изменение класса во время разработки с использованием Reflector (или эквивалентных инструментов) или во время выполнения с использованием Reflection.Emit. Тем не менее, вам придется очень плохо себя вести, чтобы идти по этому маршруту, так как это обязательно будет болезненным и хрупким.

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

2

Я думаю, что лучше всего использовать систему AOP, такую ​​как LinFu.Там в CodeProject статья объясняя это:

Introducing LinFu, Part VI: LinFu.AOP – Pervasive Method Interception and Replacement for Sealed Types in Any .NET Language

+0

Я бы рекомендовал АОП в качестве крайней меры в этом случае. Если вы можете связаться с поставщиками вашего TestClass и договориться добавить крючок для своего целевого метода (или исправить его, потому что я подозреваю, что вы пытаетесь избежать нежелательного поведения), во что бы то ни стало отдают предпочтение AOP. –

+0

Антон, помимо общего «хакерского» ощущения этого решения, есть ли какие-то конкретные недостатки? – Cray

Смежные вопросы