Можно ли расширить или изменить код класса C # во время выполнения?
Мой вопрос конкретно вращается вокруг Monkey Patching / Duck Punching или Meta Object Programming (MOP), как это происходит в языках сценариев, таких как Groovy, Ruby и т. Д.
Можно ли расширить или изменить код класса C # во время выполнения?
Мой вопрос конкретно вращается вокруг Monkey Patching / Duck Punching или Meta Object Programming (MOP), как это происходит в языках сценариев, таких как Groovy, Ruby и т. Д.
Можно ли расширить или изменить код класса C # во время выполнения?
Нет, это невозможно сделать в .NET. Вы можете написать производные классы и переопределить методы (если они виртуальные), но вы не можете изменить существующий класс. Только представьте, было ли возможно то, о чем вы просили: вы могли бы изменить поведение некоторых существующих системных классов, таких как System.String.
Вы также можете ознакомиться с методами расширения, чтобы добавить функциональность к существующему класс.
var serialObject = "STB-2".ToMySerial()
- person Gishu; 27.12.2010
moto
пакет Python, который имитирует большое количество сервисов AWS, чтобы вы могли тестировать свой готовый к отправке код, не загрязняя его хитростями и приборами для модульного тестирования.
- person Luis Artola; 27.08.2017
Вы можете добавить функциональные возможности, но не можете изменять или удалять функциональные возможности.
Вы можете расширять классы, добавляя дополнительные методы, но вы не можете их переопределить, потому что добавленные методы всегда имеют более низкий приоритет, чем существующие.
Дополнительные сведения см. В методах расширения в Руководстве по программированию на C #.
Для тех, кто до сих пор не знает ответа на этот вопрос, действительно существует современная библиотека под названием Harmony, которая относительно просто позволяет такое исправление обезьяны во время выполнения. Его основное внимание уделяется моддингу видеоигр (особенно игр, созданных с помощью Unity), но мало что мешает людям использовать его вне этого варианта использования.
Копирование примера из их введения, если у вас есть существующий класс, например:
public class SomeGameClass
{
public bool isRunning;
public int counter;
private int DoSomething()
{
if (isRunning)
{
counter++;
}
return counter * 10;
}
}
Тогда Harmony может исправить это так:
using HarmonyLib;
using Intro_SomeGame;
public class MyPatcher
{
// make sure DoPatching() is called at start either by
// the mod loader or by your injector
public static void DoPatching()
{
var harmony = new Harmony("com.example.patch");
harmony.PatchAll();
}
}
[HarmonyPatch(typeof(SomeGameClass))]
[HarmonyPatch("DoSomething")]
class Patch01
{
static AccessTools.FieldRef<SomeGameClass, bool> isRunningRef =
AccessTools.FieldRefAccess<SomeGameClass, bool>("isRunning");
static bool Prefix(SomeGameClass __instance, ref int ___counter)
{
isRunningRef(__instance) = true;
if (___counter > 100)
return false;
___counter = 0;
return true;
}
static void Postfix(ref int __result)
{
__result *= 2;
}
}
Здесь у нас есть префиксный патч, который вставляется перед запуском исходного метода, что позволяет нам устанавливать переменные внутри метода, устанавливать поля в классе метода или даже полностью пропускать исходный метод. У нас также есть постфиксный патч, который вставляется после запуска исходного метода и может управлять такими вещами, как возвращаемое значение.
Очевидно, это не так хорошо, как те виды обезьяньих исправлений, которые вы можете использовать, например, Ruby, и есть множество предостережений, которые могут помешать его полезности в зависимости от ваш вариант использования, но в тех ситуациях, когда вам действительно нужно изменить методы, Harmony - довольно проверенный подход к этому.