В моем проекте С#/ASP.NET у меня есть объект, который имеет определенные категории поведения. Каждая категория поведения физически зависит от корневого объекта, но для лучшего чтения кода я хочу четко различать категории. Я думаю, было бы интересно посмотреть, как моя реализация сравнивается с тем, что другие могут писать, чтобы решить ту же проблему.
В приведенном ниже примере у меня есть класс, который генерирует URL-адреса в разных местах на веб-сайте. На веб-сайте есть витрина, в которой есть собственный набор ссылок, к которым следует обращаться иначе, чем к URL-адресам, таким как домашняя страница.
public class WebsiteURLs
{
// One category of urls on the website is the store.
public class StoreURLs
{
private WebsiteURLs _website;
public class StoreURLs(WebsiteURLs website)
{
_website = website;
}
public string BestSellers
{
get { return _website.ResolveURL("~/store/bestSellers.html"); }
}
}
private StoreURLs _store;
public StoreURLs Store // property for generating store urls
{
get
{
if (_store == null ) {
_store = new StoreURLs(this);
}
return _store;
}
}
public string Homepage
{
get { return ResolveURL("~/default.aspx"); }
}
// .. Other Categories Here
protected string ResolveURL(string url)
{
return HttpContext.Current.Response.ApplyAppPathModifier(url);
}
}
Использование этого кода будет выглядеть примерно так:
WebsiteURLs website;
Console.WriteLine(website.Store.BestSellers);
Роберт:
Сам пример - это только один сценарий, где я обнаружил, что пытаюсь более четко организовать функциональность. Вы когда-нибудь находили, что используете префикс вокруг связанных методов. String.TrimStart(), String.TrimEnd(), String.Trim() - пример, который приходит на ум из структуры С#.
Моя попытка упорядочить код выше (с точки зрения читаемости) страдает от неспособности вложенных классов обращаться к членам внешних классов. Существует дополнительная работа по созданию внутреннего класса, потому что я должен передать ссылку экземпляра WebsiteURLs на конструктор класса StoreURLs, это почти нарушение правил кодирования С#, поскольку это поведение закрытия не является поведением вложенных классов в пределах язык. Мне любопытно, что код С# другой будет использовать в ситуациях, когда существует множество связанных функций (подумайте о десятках или сотнях методов). (Примечание: вышеприведенный код гораздо более гибкий для записи на Java, где вложенные классы имеют доступ к своим членам внешних классов).
Мой немедленный ответ, когда я вижу ваш пример, должен думать, что вы привязываете что-то относительно статическое - набор типов - к чему-то относительно динамичному - кучу URL-адресов, принадлежащих веб-сайту. Мне это плохо. Выполняя это, вы привязываете свой код к структуре и функциям веб-сайта. Любое изменение любого URL-адреса в любом месте веб-сайта, на который вы привязаны, заставляет вас перестраивать и передислоцировать ваше программное обеспечение.
Итак, если вы собираетесь это сделать, у вас должна быть довольно веская причина. Что ты из этого делаешь? Возможность использовать проверку типов (и, возможно, IntelliSense) в иерархии веб-страниц. Вы платите действительно значительную стоимость, чтобы получить это.
Стоит ли это того? Это:
url = website.Store.BestSellers;
действительно намного лучше, чем это:
url = website.GetUrl("Store.BestSellers");
что это стоит того объема работы, который вам нужно будет сделать, чтобы добиться этого?
Есть, конечно, обстоятельства, при которых ответ на этот вопрос может быть "да". Но я не стал бы тратить еще одну минуту на этот проект, не будучи уверенным, что знаю это.
Я согласен с Робертом. Еще одна вещь, которую вы можете сделать, - создать файл ресурсов (ключ/значение) URL-адресов вашего сайта и обратиться к нему следующим образом:
string url = Resources.Navigation.Home;
Это дает вам автоматическую проверку имен в compiletime, а не во время выполнения (так как строка не будет оцениваться до тех пор)
Я бы установил путь в файле web.config, файле ресурсов или в базе данных, делая это, вы получаете много преимуществ, например, вы можете использовать другую конфигурацию для тестирования/производства, вы можете переключиться на другую страницу, просто отредактировав свою конфигурацию без изменения источника и перекомпилировав...
Я не уверен, что понимаю цель. Но...
Я считаю, что просто создаю интерфейс или базовый класс, который выполняет большую часть работы по генерации и просто извлекает из него для каждой категории.
Или создайте класс factory, который отвечает на перечисление категории.
Использовать С# Регионы. Регионы будут правильно обозначать ваш код.
public class WebsiteURLs
{
#region StoreURLs sub-class
// One category of urls on the website is the store.
public class StoreURLs
{
private WebsiteURLs _website;
public class StoreURLs(WebsiteURLs website)
{
_website = website;
}
public string BestSellers
{
get { return _website.ResolveURL("~/store/bestSellers.html"); }
}
}
#endregion
#region StoreURLs prop. accessor
private StoreURLs _store;
public StoreURLs Store // property for generating store urls
{
get
{
if (_store == null ) {
_store = new StoreURLs(this);
}
return _store;
}
}
#endregion
#region Homepage
public string Homepage
{
get { return ResolveURL("~/default.aspx"); }
}
#endregion
#region Methods
// .. Other Categories Here
protected string ResolveURL(string url)
{
return HttpContext.Current.Response.ApplyAppPathModifier(url);
}
#endregion
}