Я просто смотрю на проект, и я вижу что-то работающее, которое, как я думал, не должно работать.
Если посмотреть на фрагмент ниже я нахожусь в пространстве имен CustomFields.DateTimeField.Drivers
, и только другие, using
утверждения в этом файле и другие пространства имен ниже CustomFields.DateTimeField
.
Но если вы посмотрите на public class DateTimeFieldDriver
он использует тип Fields.DateTimeField
.
Глядя на определение DateTimeField
thats в пространстве имен CustomFields.DateTimeField.Fields
но я только установил для своих дочерних пространств имена.
Поэтому вопрос двоякий: почему это работает? это считается плохой практикой?
Рассматриваемый фрагмент:
using System;
using JetBrains.Annotations;
using Orchard;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Localization;
using CustomFields.DateTimeField.Settings;
using CustomFields.DateTimeField.ViewModels;
namespace CustomFields.DateTimeField.Drivers {
[UsedImplicitly]
public class DateTimeFieldDriver : ContentFieldDriver<Fields.DateTimeField> {
public IOrchardServices Services { get; set; }
private const string TemplateName = "Fields/Custom.DateTime"; // EditorTemplates/Fields/Custom.DateTime.cshtml
public DateTimeFieldDriver(IOrchardServices services) {
Services = services;
T = NullLocalizer.Instance;
}
Проект можно загрузить здесь, если вы хотите его изучить (проект MVC2).
Когда вы объявляете код внутри определенного пространства имен, например, CustomFields.DateTimeField.Drivers
, вы также неявно импортируете все "родительские" пространства имен.
В этом случае у вас подразумевается использование для CustomFields
и CustomFields.DateTimeField
. Вот почему вам не нужно указывать явную инструкцию using
для типов в CustomFields.DateTimeField
и, кроме того, для содержащихся в ней пространств имен.
Таким образом, Fields.DateTimeField
обнаруживается путем объединения CustomFields.DateTimeField
(подразумеваемого пространства имен) с Fields.DateTimeField
(явным пространством имен) для разрешения на CustomFields.DateTimeField.Fields.DateTimeField
.
И нет, насколько я знаю, это не считается плохой практикой.
В С#, когда вы находитесь в пространстве имен, вы используете неявное using
для каждого из родительских пространств имен. Например, в этом файле:
using System;
namespace Foo.Bar.Baz {
class Qux {
}
}
\EOF
То же, что и этот файл:
using System;
using Foo;
using Foo.Bar;
namespace Foo.Bar.Baz {
class Qux {
}
}
\EOF
Если у вас есть импортированное пространство имен, вам не нужно указывать полное пространство имен для доступа к элементам дерева пространства имен для дочернего узла, если оно имеет тот же префикс, что и импортированное пространство имен:
using Foo;
using Foo.Bar;
namespace Foo.Bar.Baz {
class Qux {
}
}
namespace Foo.Bar.Norf {
class Guf : Bar.Baz.Qux { // namespace 'Foo.' is implicitly assumed to prefix the namespace reference 'Bar.Baz'
}
}
\EOF
Вы испытываете эти два эффекта в сочетании: неявное использование префикса пространства имен для неявно импортированного пространства имен.
Что касается "плохой практики", опытные разработчики С# будут знакомы с этим нюансом, но, как правило, это не проблема, если у вас нет неоднозначных имен.
В качестве подсказки попытайтесь свести к минимуму количество пространств имен и их глубин. Например, в вашем случае я вижу, что вы сохраняете специфичные для DateTime вещи в своем собственном пространстве имен DateTimeField
. У меня плохой запах кода. Я бы просто поместил все в пространство имен CustomFields
, тем более, что вы давали каждому типу имя префикс DateTime
любом случае, поэтому он просто дважды печатает.
FxCop будет жаловаться, если у вас меньше 5 типов в пространстве имен, кстати.
Обновление: я рассмотрел спецификацию С# (http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf), раздел 16, но я не могу найти какую-либо часть он утверждает, что родительские пространства имен импортируются неявно, что странно.
DateTimeField
), определенно считается не таким хорошим / безопасным, чтобы его можно было попробовать дома.