2

在我的 C#/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() 是从 C# 框架中想到的一个示例。

我试图组织上面的代码(从可读性的角度来看)受到嵌套类无法访问外部类成员的影响。构建内部类涉及额外的工作,因为我必须将 WebsiteURLs 实例的引用传递给 StoreURLs 类的构造函数,这几乎违反了 C# 编码实践,因为这种闭包行为不是嵌套类的行为语。我很好奇其他人在存在大量相关功能的情况下会使用什么 C# 代码(想想数十或数百种方法)。(注意:上面的代码在 Java 中编写起来更加流畅,其中嵌套类确实可以访问它们的外部类成员)。

4

5 回答 5

2

当我看到您的示例时,我的直接反应是认为您正在将一些相对静态的东西 - 一组类型 - 绑定到相对动态的东西 - 一堆属于网站的 URL。我闻起来不对。这样做会使您的代码与网站的结构和功能紧密结合。对您绑定到的网站中任何位置的任何 URL 的任何更改都会迫使您重新构建和重新部署您的软件。

所以,如果你要这样做,你必须有一个很好的理由。你从中得到什么?在网页层次结构上使用类型检查(可能还有 IntelliSense)的能力。你要付出很大的代价才能得到这个。

这值得么?这是:

url = website.Store.BestSellers;

真的比这好多了:

url = website.GetUrl("Store.BestSellers");

为了实现它而付出的努力值得吗?

在某些情况下,这个问题的答案可能是“是”。但如果我不确定我是否知道,我不会再花一分钟在这个设计上。

于 2009-07-29T06:31:24.697 回答
0

我会在 web.config、资源文件或数据库中配置路径,这样做,您会获得很多优势,例如您可以使用不同的配置进行测试/生产,您可以切换到另一个页面,只需编辑您的配置而不进行更改在源代码和重新编译...

于 2009-07-29T07:24:41.093 回答
0

我同意罗伯特。您可以做的另一件事是创建站点 url 的资源文件(键/值)并像这样引用它:

字符串 url = Resources.Navigation.Home;

它让您在编译时而不是运行时自动检查名称(因为在此之前不会评估字符串)

于 2009-07-29T07:30:32.033 回答
0

使用C# 区域。区域将正确分类您的代码。

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
}
于 2009-07-29T05:35:31.907 回答
0

我不确定我是否理解目标。但...

我相信我会创建一个接口或基类来完成大部分生成工作,并为每个类别从中派生。

或者,创建一个响应类别枚举的工厂类。

于 2009-07-29T05:37:38.113 回答