Альтернативы “использующему” направляющему ключевому слову в C#?

(извлек некоторое объяснение, которое было скрыто в комментариях в другом ответе)

проблема заключается в следующей строке:

this.dom.addEventListener("click", self.onclick, false);

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

проблема может быть решена путем обертывания функции (с, он - ссылка на объект) в закрытии следующим образом:

this.dom.addEventListener(
  "click",
  function(event) {self.onclick(event)},
  false);

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

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

function bind(scope, fn) {
    return function () {
        fn.apply(scope, arguments);
    };
}

обновленный код был бы тогда похож:

this.dom.addEventListener("click", bind(this, this.onclick), false);

Function.prototype.bind часть ECMAScript 5 и обеспечивает ту же функциональность. Таким образом, можно сделать:

this.dom.addEventListener("click", this.onclick.bind(this), false);

Для браузеров, которые еще не поддерживают ES5, , MDN обеспечивает следующий контейнер :

if (!Function.prototype.bind) {  
  Function.prototype.bind = function (oThis) {  
    if (typeof this !== "function") {  
      // closest thing possible to the ECMAScript 5 internal IsCallable function  
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");  
    }  

    var aArgs = Array.prototype.slice.call(arguments, 1),   
        fToBind = this,   
        fNOP = function () {},  
        fBound = function () {  
          return fToBind.apply(this instanceof fNOP  
                                 ? this  
                                 : oThis || window,  
                               aArgs.concat(Array.prototype.slice.call(arguments)));  
        };  

    fNOP.prototype = this.prototype;  
    fBound.prototype = new fNOP();  

    return fBound;  
  };  
} 

5
задан crokusek 24 March 2016 в 19:19
поделиться

5 ответов

Плох не сам оператор using - это если вы получите слишком много из них.

Такой оператор, как using System; редко представляет собой проблему сама по себе, но если у вас много (я бы сказал, более 3-6, в зависимости от того, какие) в одном файле кода, это может быть признаком сильной связи .

Вы могли бы с таким же успехом применить аналогичное эмпирическое правило к количеству ссылок в самом проекте.

Решением сильной связи является программирование интерфейсов и внедрение зависимостей (DI).

1293]. Способ ProgId делать вещи, которые вы помните из VB, был просто COM в действии. По сути, вы использовали этот ProgId, чтобы получить ссылку на экземпляр, реализующий желаемый интерфейс. Обратной стороной было то, что это работало только тогда, когда COM-объект был зарегистрирован повсеместно. Помните ад dll?

Вы по-прежнему можете применить тот же принцип, используя определенные разновидности DI, только теперь интерфейс является типом .NET и не определен в IDL, и вам нужен какой-то контейнер DI для обеспечения конкретной реализации.

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

использование - это просто ярлык для пространств имен, они не являются ссылками на внешние файлы. Следовательно, это просто не имеет смысла.

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

Взгляните на классы Assembly и AppDomain для загрузки сборок,

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

Я полагаю, что Боб Мартин на самом деле имеет в виду раннее и позднее связывание.

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

Обычно директивы using (а не оператор using) идут рука об руку вместе с прямым обращением к внешней сборке. т.е. Вы добавляете ссылку на сборку, а затем добавляете директивы using, чтобы избежать необходимости вводить полную иерархию пространства имен при использовании внешних типов.

Итак, если вы обнаружите, что в вашем коде есть большое количество директив using вверху, это возможно, что вы напрямую ссылаетесь на многие другие типы и, таким образом, увеличиваете связь / зависимость вашего кода от этих типов.

Я предполагаю, что именно поэтому Боб называет их плохими. Ответ на вопрос "это действительно плохо?" является очень субъективным и зависит от контекста.

В общем, разделение компонентов почти всегда является хорошей целью при разработке программного обеспечения. Это потому, что это позволяет вам изменять части вашей системы с минимальным влиянием на остальную систему. Прочитав одну или две книги Боба Мартинса, я ожидал, что это именно то, что он имеет в виду.

7
ответ дан 18 December 2019 в 07:10
поделиться

Вы можете использовать отражение:

// Load the assembly
Assembly assembly = Assembly.LoadFrom(@"c:\path\Tools.dll");
// Select a type
Type type = assembly.GetType("Tools.Utility");
// invoke a method on this type
type.InvokeMember("SomeMethod", BindingFlags.Static, null, null, new object[0]);
2
ответ дан 18 December 2019 в 07:10
поделиться

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

Лично я бы не стал этого делать, чтобы избежать спаривания. Для меня это плохое использование отражения, и я бы предпочел добавить его в проект и ссылаться на него, если нет конкретной причины, почему бы этого не сделать. Отражение увеличивает накладные расходы на систему, и вы не получаете преимущества безопасности времени компиляции.

1
ответ дан 18 December 2019 в 07:10
поделиться
Другие вопросы по тегам:

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