在我的C#/ ASP.NET项目中,我有一个具有某些行为类别的对象。每个行为类别在物理上依赖于根对象,但为了使代码更好地阅读,我希望明确区分类别。我认为看看我的实现与其他人为解决同样的问题所能写的内容相比会很有趣。
在下面的示例中,我有一个类,它可以生成网站上不同位置的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#代码会在存在大量相关功能的情况下使用C#代码(想想数十或数百种方法)。 (注意:上面的代码在Java中写得更流畅,其中嵌套类可以访问其外部类成员)。
答案 0 :(得分:2)
当我看到你的例子时,我的立即回应是认为你将一些相对静态的东西 - 一组类型 - 绑定到一些相对动态的东西 - 一堆属于一个网站的URL。那对我来说有点不对劲。这样做会将代码紧密地耦合到网站的结构和功能上。对您绑定的网站中任何网址的任何更改都会强制您重建和重新部署软件。
所以,如果你要这样做,你必须有一个很好的理由。你有什么从中得到的?能够在网页层次结构上使用类型检查(以及可能的IntelliSense)。你付出了相当大的代价才能得到这个。
值得吗?是这样的:
url = website.Store.BestSellers;
真的比这更好:
url = website.GetUrl("Store.BestSellers");
为了达到这个目的,你需要投入大量的工作吗?
在某些情况下,该问题的答案可能是“是”。但是我不会在这个设计上再花一分钟而不确定我知道它。
答案 1 :(得分:0)
使用C# Regions 。区域将正确地对您的代码进行分类。
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
}
答案 2 :(得分:0)
我不确定我是否理解目标。但...
我相信我只会创建一个接口或基类来完成大部分的生成工作,并从每个类别派生出来。
或者,创建一个响应类别枚举的工厂类。
答案 3 :(得分:0)
我会在web.config,资源文件或数据库中配置路径, 这样做,您获得了很多优势,例如您可以使用不同的配置进行测试/生产,您可以切换到另一个页面,只需编辑您的配置而无需更改源代码并重新编译...
答案 4 :(得分:0)
我同意罗伯特的观点。您可以做的另一件事是创建站点网址的资源文件(键/值)并像这样引用它:
string url = Resources.Navigation.Home;
它允许您在编译时而不是运行时自动检查名称(因为在此之前不会对字符串进行求值)