Существует ли способ обмануть JIT-компилятор.NET в выполнение другого метода?

Существует ограничение при использовании динамического импорта с «переменными частями», такими как import(`${path}`), поскольку ${path} является переменной.

Во время создания пакета Webpack

В вашем случае, когда компонент import(`${path}`) в Dynamic назывался webpack, создавал пакет. Этот комплект был для FirstComponent компонента. Внутри этого пакета веб-пакет содержит список компонентов, которые можно динамически импортировать с помощью «переменных частей» в компоненте FirstComponent. Он содержал только файлы, которые находились в той же папке, где находился компонент FirstComponent. Это потому, что вы использовали import(`${path}`) в FirstComponent.

Все это происходит потому, что webpack при компиляции не знает, какой будет точный путь импорта во время выполнения, так как вы используете динамический импорт с «переменными частями».

Во время запроса приложения React

Когда в компоненте Dynamic было выполнено import(`${path}`). Пакет для FirstComponent был запрошен. Как только пакет был получен, и он выполнил свой код, и path, который вы указали в качестве компонента props - FirstComponent, не было в списке компонентов, которые можно динамически импортировать с помощью «переменных частей».

То же самое относится и к компоненту Dynamic, если вы попытаетесь динамически импортировать файлы с «переменными частями» для файлов, которые находятся вне папки src, вы получите ту же ошибку.

Итак, чтобы решить эту проблему, у вас есть пара опций

1) Поместите оба файла в одну папку

, т.е.

'src/Components/FirstComponent'

'src/Components/Footer'

И используйте

// In FirstComponent.js
   componentDidMount() {
      const { path } = this.props;
      import(`${path}`)
      .then(module => this.setState({ module: module.default }))   
   }


{Component && <Component path='./Footer' />} // Index.js

2) быть более точным, насколько это возможно

т.е.

// In FirstComponent.js
 componentDidMount() {
      const { path } = this.props;
      import(`../FooterComp/${path}`)
      .then(module => this.setState({ module: module.default }))   
 }

И использовать

{Component && <Component path='Footer' />} //  In index.js

ОБНОВЛЕНИЕ

Пакет, созданный веб-пакетом для componentDidMount:

1) для динамического импорта с переменными, но более конкретным способом, например import(`../FooterComp/${path}`)

 _createClass(App, [{
        key: "componentDidMount",
        value: function componentDidMount() {
          var _this2 = this;

          var path = this.props.path;
          // "import(`../FooterComp/${path}`)" is converted to code below
          __webpack_require__(/*! ../FooterComp */ "./src/FooterComp lazy recursive ^\\.\\/.*$")("./" + path)
          .then(function (module) {
            return _this2.setState({ module: module.default });
          });

Код для [ 1126] в связке

/***/ "./src/FooterComp lazy recursive ^\\.\\/.*$":
/*!**************************************!*\
  !*** ./src/FooterComp lazy ^\.\/.*$ ***!
  \**************************************/
/*! dynamic exports provided */
/*! all exports used */
/***/ (function(module, exports, __webpack_require__) {

var map = {
    "./Footer": [
        "./src/FooterComp/Footer.jsx",
        0
    ],
    "./Footer.jsx": [
        "./src/FooterComp/Footer.jsx",
        0
    ]
};
function webpackAsyncContext(req) {
    var ids = map[req];
    if(!ids)
        // Code throwing "ERROR"
        return Promise.reject(new Error("Cannot find module '" + req + "'."));
    return __webpack_require__.e(ids[1]).then(function() {
        return __webpack_require__(ids[0]);
    });
};
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
    return Object.keys(map);
};
webpackAsyncContext.id = "./src/FooterComp lazy recursive ^\\.\\/.*$";
module.exports = webpackAsyncContext;

/***/ })

2) для динамического импорта с переменными, т.е. import(`${path}`)

_createClass(App, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      var _this2 = this;

      var path = this.props.path;
         // "import(`${path}`)" is converted to code below
      __webpack_require__(/*! . */ "./src/Components lazy recursive ^.*$")("" + path).then(function (module) {
        return _this2.setState({ module: module.default });
      });

Код для ./src/Components lazy recursive ^.*$

/***/ "./src/Components lazy recursive ^.*$":
/*!**********************************!*\
  !*** ./src/Components lazy ^.*$ ***!
  \**********************************/
/*! dynamic exports provided */
/*! all exports used */
/***/ (function(module, exports, __webpack_require__) {

var map = {
    "./FirstComponent": [
        "./src/Components/FirstComponent.jsx"
    ],
    "./FirstComponent.jsx": [
        "./src/Components/FirstComponent.jsx"
    ]
};
function webpackAsyncContext(req) {
    var ids = map[req];
    if(!ids)
        // Code throwing "ERROR"
        return Promise.reject(new Error("Cannot find module '" + req + "'."));
    return Promise.all(ids.slice(1).map(__webpack_require__.e)).then(function() {
        return __webpack_require__(ids[0]);
    });
};
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
    return Object.keys(map);
};
webpackAsyncContext.id = "./src/Components lazy recursive ^.*$";
module.exports = webpackAsyncContext;

/***/ }),
7
задан Peter Mortensen 2 October 2019 в 02:07
поделиться

5 ответов

Да, можно сделать это!

Сцепите getJit метод mscorjit. И Вас спросят каждый раз, если какой-либо метод потребует jitting. Можно передать то, что Вы хотите.

Некоторые средства защиты.NET работают как это.

6
ответ дан 6 December 2019 в 10:55
поделиться

Поскольку Вы говорите, что это не легко, и это даже не может быть возможно. Если я помню правильно, что код будет включать адрес JIT-компилятора для метода, который не был скомпилирован. Таким образом, когда Вы пытаетесь назвать этот метод, JIT-компилятор сделает свое задание и вставит адрес в недавно скомпилированный метод. Если можно изменить этот адрес, Вы можете вставлять вызов в свой собственный код. Как Вы сделали бы, это необнаруженное вне меня. Я, конечно, надеюсь, что CLR обнаружит этот вид вмешательства.

Я не думаю, что Профильный API поможет Вам в этом случае (как предложено Leppie), поскольку Вы не пытаетесь изменить MSIL. Если Вы думаете иначе, что эта статья может быть полезной, поскольку она описывает то, что необходимо сделать для реализации то, что делает TypeMock.

2
ответ дан 6 December 2019 в 10:55
поделиться

В дополнение к способности использовать ICorProfiler и перезапись Вашего метода перед ним монеты в пять центов, Вы могли использовать ICorDebug (MDBG справился соединенный интерфейсом). Установите точку останова, когда хиты точки останова установят следующий оператор на Ваш код прерывания. Весь этот процесс может быть сделан из кода, но действительно навязчив, и Вам будет нужен процесс "наблюдателя" для координирования этого.

Другой вещью, которая стоит посмотреть на, является проект PostSharp, который дает Вам методы входа и выхода, если Вы применяете атрибуты.

0
ответ дан 6 December 2019 в 10:55
поделиться

Это возможно через Профильный API. Я никогда не использовал его, но это используется для подобной цели в TypeMock.

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

Редактирование 2: Doh, сначала хит!

10
ответ дан 6 December 2019 в 10:55
поделиться

Я не попытался бы смешать непосредственно с памятью, и я не уверен, что это даже возможно вместо этого, что можно использовать профилировщика API - существует несколько примеров там, но никакая реальная документация. Взгляните на статью MSDN Magazine - Переписывают Код MSIL на лету с Платформой.NET Профильный API

0
ответ дан 6 December 2019 в 10:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: