【感谢放歌,阿非,sp123,vrhero的指点】经过指点后的最后版本

tiandiyuzhou3 2012-01-06 03:21:25
感谢放歌,阿非,sp123,vrhero的指点,让我学到了很多。以及一些顶帖的朋友们。感谢。
这是最后修改的结果。麻烦看下还有哪些地方需要改进的。
再次感谢你们。
关于PageFactory中的GetPage()方法,除了用反射,还有其他更好的方法吗?

模版规则属性类

public class TemplateRuleBuilder
{
public TemplateRuleBuilder(int LevelID, string Page)
{
this.page = Page;
this.path = string.Format("/Template/{0}/{1}.html", LevelID, Page);
isCache = GetSetting(LevelID.ToString()) == "true" ? true : false;
cacheKey = isCache ? GetSetting(LevelID + CacheKeyPara) + Page : "";
}
public string GetSetting(string key)
{
return ConfigurationManager.AppSettings[key];
}
private const string CacheKeyPara = "CacheKey";
private bool isCache;
/// <summary>
/// 是否需要缓存
/// </summary>
public bool IsCache
{
get { return isCache; }
set { isCache = value; }
}
private string cacheKey;
/// <summary>
/// 缓存键值
/// </summary>
public string CacheKey
{
get { return cacheKey; }
set { cacheKey = value; }
}
private string path;
/// <summary>
/// 模版路径
/// </summary>
public string Path
{
get { return path; }
set { path = value; }
}
private string page;
/// <summary>
/// 模版文件名
/// </summary>
public string Page
{
get { return page; }
set { page = value; }
}
}

读取模板类

public class TemplateRule
{
public TemplateRule(int LevelID, string Page)
{
trb = new TemplateRuleBuilder(LevelID, Page);
}
/// <summary>
/// 模板相关属性
/// </summary>
private TemplateRuleBuilder trb;
/// <summary>
/// 获取模版
/// </summary>
/// <returns></returns>
public string GetTemplate()
{
string template = string.Empty;
if (!File.Exists(HttpContext.Current.Server.MapPath(trb.Path)))
return template;
if (trb.IsCache)
{
if (HttpContext.Current.Cache[trb.CacheKey] == null)
HttpContext.Current.Cache.Insert(trb.CacheKey, ReadTemplate(), null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20));
template = HttpContext.Current.Cache[trb.CacheKey].ToString();
}
else
template = ReadTemplate();
return template;
}
/// <summary>
/// 读取模版
/// </summary>
/// <returns></returns>
protected string ReadTemplate()
{
string result = string.Empty;
StreamReader sr = null;
try
{
sr = new StreamReader(HttpContext.Current.Server.MapPath(trb.Path), Encoding.GetEncoding("gb2312"));
result = sr.ReadToEnd();
}
catch
{
}
finally
{
if (sr != null)
{
sr.Close();
sr.Dispose();
}
}
return result;
}
}

页面工厂类

public class PageFactory
{
private string page;
private string template;
private Model.CompanyTbl model;
public PageFactory(string page, string template, Model.CompanyTbl model)
{
this.page = page;
this.template = template;
this.model = model;
}
public delegate string PageDelegate();
public string GetPage()
{
if (template.Length == 0)
return template;
PageHandler ph = new PageHandler(template, model);
System.Reflection.MethodInfo mi = ph.GetType().GetMethod("Get" + page, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
PageDelegate pd = (PageDelegate)Delegate.CreateDelegate(typeof(PageDelegate), ph, mi, false);
if (pd == null)
return string.Empty;
return pd();
}
}


...全文
270 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
tiandiyuzhou3 2012-01-12
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 sandy945 的回复:]
嗯,大体上就是这个意思。

细节的地方可以写的艺术些 : )
[/Quote]谢谢非哥的指点。
阿非 2012-01-12
  • 打赏
  • 举报
回复
嗯,大体上就是这个意思。

细节的地方可以写的艺术些 : )
tiandiyuzhou3 2012-01-11
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 sandy945 的回复:]
引用 12 楼 tiandiyuzhou3 的回复:


TemplateRule 是不知道 TemplateRuleBuilder 存在的

而 TemplateRuleBuilder 也只是知道自己需要构建一个 TemplateRule 类型 或者派生自 TemplateRule 类型的一个实例
[/Quote]这句一直很不明白红色那句。
难道是这样吗?

public class TemplateRule
{
public string CacheKey;
public boll IsCache;
public string Path;
public string Page;
///...
}
public Class TemplateRuleBuilder :TemplateRule
{
public TemplateRuleBuilder(string CacheKey,bool IsCache,string Path,string Page)
{
//....
}
}

是这样吗?然后通过TemplateRuleBuilder 实例访问父类TemplateRule?
tiandiyuzhou3 2012-01-11
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 sandy945 的回复:]
你可以先看下生成器模式

但不用按照那个来做,理解思想就可以了。
[/Quote]非哥,我看了那个动软代码生成器生成的抽象工厂三层,那个模式我理解,就是抽离出一个IDAL层,然后通过配置config文件来改变加载的模块,然后通过反射实例化对应类,返回给对应DAL接口。
可是还是不太明白额。
tiandiyuzhou3 2012-01-11
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 sandy945 的回复:]
而 TemplateRuleBuilder 也只是知道自己需要构建一个 TemplateRule 类型 或者派生自 TemplateRule 类型的一个实例
--------------------------------
而 TemplateRuleBuilder 也只是知道自己需要构建 "一个 TemplateRule 类型" 或者 "派生自 TemplateRule 类型" 的一个实例
……
[/Quote]有点明白了
TemplateRulBuilder只知道要构件一个TempalteRule类型,至于TemplateRule类型里面实现了什么方法不去关心,而TemplateRule所需要的参数由TemplateRuleBuider类创建,是这样吗?

public class TemplateRuleBuilder
{
public TemplateRule GetTemplateRule()
{
string page = ...;
string path = string.Format("/Template/{0}/{1}.html", LevelID, Page);
bool isCache = GetSetting(LevelID.ToString()) == "true" ? true : false;
string cacheKey = isCache ? GetSetting(LevelID + CacheKeyPara) + Page : "";

return new TemplateRule(page,path,iscache...)
}
}

这样子吗?
阿非 2012-01-11
  • 打赏
  • 举报
回复
而 TemplateRuleBuilder 也只是知道自己需要构建一个 TemplateRule 类型 或者派生自 TemplateRule 类型的一个实例
--------------------------------
而 TemplateRuleBuilder 也只是知道自己需要构建 "一个 TemplateRule 类型" 或者 "派生自 TemplateRule 类型" 的一个实例

不是 TemplateRuleBuilder 继承 TemplateRule
阿非 2012-01-11
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 tiandiyuzhou3 的回复:]

引用 21 楼 sandy945 的回复:
你可以先看下生成器模式

但不用按照那个来做,理解思想就可以了。
非哥,我看了那个动软代码生成器生成的抽象工厂三层,那个模式我理解,就是抽离出一个IDAL层,然后通过配置config文件来改变加载的模块,然后通过反射实例化对应类,返回给对应DAL接口。
可是还是不太明白额。
[/Quote]
不太明白那里?
tiandiyuzhou3 2012-01-10
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 sandy945 的回复:]
引用 12 楼 tiandiyuzhou3 的回复:


TemplateRule 是不知道 TemplateRuleBuilder 存在的

而 TemplateRuleBuilder 也只是知道自己需要构建一个 TemplateRule 类型 或者派生自 TemplateRule 类型的一个实例
[/Quote]非哥,还是想不明白您的意思,可以写个示例不!
阿非 2012-01-10
  • 打赏
  • 举报
回复
你可以先看下生成器模式

但不用按照那个来做,理解思想就可以了。
阿非 2012-01-09
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 tiandiyuzhou3 的回复:]

引用 9 楼 sandy945 的回复:
要是反射的话

mi.Invoke(参数);

就是你需要的了,用不上委托了。

用委托其实是为了避开反射
用反射+委托,是因为开了这篇帖子。
http://blog.csdn.net/zheng_/article/details/5344472
里面的测试代码委托+反射效率会好点。

而我自己的测试代码,委托+反射会相对Invo……
[/Quote]
具体没细看,不过我之前说的用委托避免反射的意思是 如果环境允许可以用表达式来构建委托
这样来避免反射。
你使用缓存委托的方式是可以的,只是第一次用反射来构建
hllfl 2012-01-09
  • 打赏
  • 举报
回复
有人。
阿非 2012-01-09
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 tiandiyuzhou3 的回复:]
[/Quote]

TemplateRule 是不知道 TemplateRuleBuilder 存在的

而 TemplateRuleBuilder 也只是知道自己需要构建一个 TemplateRule 类型 或者派生自 TemplateRule 类型的一个实例
tiandiyuzhou1 2012-01-09
  • 打赏
  • 举报
回复
星期一了 不知道有没有人。
tiandiyuzhou3 2012-01-07
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 qldsrx 的回复:]
你所谓的复用性不高,就是当PageFactory.page增加类型的时候,要同时修改PageFactory的GetPage函数和为PageHandler类增加对应的"Get"+page的函数,那么为啥不考虑直接在PageHandler内部处理这个page呢?比如在PageHandler类里定义一个函数叫public string GetPage(string page),那么page类型有任何改动……
[/Quote]
[Quote=引用 11 楼 qldsrx 的回复:]
引用 9 楼 sandy945 的回复:
要是反射的话

mi.Invoke(参数);

就是你需要的了,用不上委托了。

用委托其实是为了避开反射

用委托不是为了避开反射,而是提供了一个缓存的对象。如果直接缓存MethodInfo,那么每次使用的时候都调用Invoke,速度还是不够快,但是如果缓存了一个委托的对象,那么执行速度和直接执行一个实名方法是一样快的,只不过第一次使用……
[/Quote]
非常感谢青龙白虎的指点
由于一人只能连续回复3次,这边我整和一起回复。

1:如果用原来的switch确实很直白,改动也很小,也许是我自己的问题,我想做得更灵活点,而就像您说的,当你考虑效率的时候,有时代码就会写得比较多,当你考虑代码简洁(复用性高)的时候,效率就会降低。确实是这样。我会根据情况而定。

2:如果用委托反射+缓存的话这个要管理好缓存,会员有很多个,而每个会员都要把相应方法缓存起来,这个对我来说还比较艰巨,还要考虑缓存命中率等等。
tiandiyuzhou3 2012-01-07
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sandy945 的回复:]
要是反射的话

mi.Invoke(参数);

就是你需要的了,用不上委托了。

用委托其实是为了避开反射
[/Quote]用反射+委托,是因为开了这篇帖子。
http://blog.csdn.net/zheng_/article/details/5344472
里面的测试代码委托+反射效率会好点。

而我自己的测试代码,委托+反射会相对Invoke快点,不要测试了相差不大。

//Stopwatch sw = new Stopwatch();
//Program p = new Program();
//MethodInfo mi = p.GetType().GetMethod("Test");
//sw.Start();
//for (int i = 0; i < 1000000; i++)
//{
// if (mi != null)
// mi.Invoke(p, new object[] { 1 });
//}
//sw.Stop();
//Console.WriteLine(sw.ElapsedMilliseconds);

Stopwatch sw = new Stopwatch();
Program p = new Program();
MethodInfo mi = p.GetType().GetMethod("Test");
sw.Start();
MyDelegate my;
for (int i = 0; i < 1000000; i++)
{
my = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), p, mi, false);
my(2);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
tiandiyuzhou3 2012-01-07
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 sandy945 的回复:]
TemplateRuleBuilder 是要构建 TemplateRule 的

你应该保留之前的 TemplateRule,只是它的相关属性的值 是由外界注入给它的

而注入这个动作是由 TemplateRuleBuilder 去做

TemplateRule 要做的事就是按照你指定好的规则进行操作,它不关心相应参数的取值

从数据库还是配置文件还是其他什么地方 都和它无关。
……
[/Quote]
非常感谢非哥3个帖子一直以来的指点,我明白您的意思了。以下是更改后的,不知道是不是这样!

TemplateRuleBuilder构造函数改了,里面的配置它不用去关系,由外界传入。

public TemplateRuleBuilder(bool isCache, string CacheKey, string Path, string Page)
{
this.isCache = isCache;
this.cacheKey = CacheKey;
this.path = Path;
this.page = Page;
}

而TemplateRule也不关系TemplateRuleBuilder怎么配置参数的,由构造函数注入。

public TemplateRule(TemplateRuleBuilder trb)
{
this.trb = trb;
}

页面调用的时候

protected void Page_Load(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(Request.QueryString["ID"]) && Common.RegexCommon.IsNumber(Request.QueryString["ID"]))
{
//...
TemplateRule tr; string template = string.Empty;
if (model.CompPassed > 0)
tr = new TemplateRule(GetBuilder(model.LevelID, Page));
else
tr = new TemplateRule(GetBuilder(10000, Page));
template = tr.GetTemplate();
PageFactory pf = new PageFactory(Page, template, model);
Response.Write(pf.GetPage());
}
}
}
public TemplateRuleBuilder GetBuilder(int LevelID, string Page)
{
TemplateRuleBuilder trb;
bool isCache = GetSetting(LevelID.ToString()) == "true" ? true : false;
string path = string.Format("/Template/{0}/{1}.html", LevelID, Page);
string cacheKey = isCache ? GetSetting(LevelID + "CacheKey") + Page : "";
trb = new TemplateRuleBuilder(isCache, cacheKey, path, Page);
return trb;
}
public string GetSetting(string key)
{
return ConfigurationManager.AppSettings[key];
}
qldsrx 2012-01-06
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sandy945 的回复:]
要是反射的话

mi.Invoke(参数);

就是你需要的了,用不上委托了。

用委托其实是为了避开反射
[/Quote]
用委托不是为了避开反射,而是提供了一个缓存的对象。如果直接缓存MethodInfo,那么每次使用的时候都调用Invoke,速度还是不够快,但是如果缓存了一个委托的对象,那么执行速度和直接执行一个实名方法是一样快的,只不过第一次使用的时候较慢——要先反射,然后创建委托。

刚才发帖快了点,其实我还想说的是,如果既要复用性,又要效率,就该考虑反射后创建的委托进行缓存,这样两者都兼顾了。(做得好点的话,设置一个属性记录委托的使用率,当缓存达到预定上限的时候,自动删除使用率较低的缓存)
qldsrx 2012-01-06
  • 打赏
  • 举报
回复
你所谓的复用性不高,就是当PageFactory.page增加类型的时候,要同时修改PageFactory的GetPage函数和为PageHandler类增加对应的"Get"+page的函数,那么为啥不考虑直接在PageHandler内部处理这个page呢?比如在PageHandler类里定义一个函数叫public string GetPage(string page),那么page类型有任何改动,也只需要修改PageHandler类了。
当然,按照你原来的修改,只不过要同时修改2个类而已,效率上没问题。当你考虑效率的时候,有时代码就会写得比较多,当你考虑代码简洁(复用性高)的时候,效率就会降低,针对你的疑问“除了用反射,还有其他更好的方法吗”,改回原来的判断效率可以提高。
阿非 2012-01-06
  • 打赏
  • 举报
回复
要是反射的话

mi.Invoke(参数);

就是你需要的了,用不上委托了。

用委托其实是为了避开反射
阿非 2012-01-06
  • 打赏
  • 举报
回复
TemplateRuleBuilder 是要构建 TemplateRule 的

你应该保留之前的 TemplateRule,只是它的相关属性的值 是由外界注入给它的

而注入这个动作是由 TemplateRuleBuilder 去做

TemplateRule 要做的事就是按照你指定好的规则进行操作,它不关心相应参数的取值

从数据库还是配置文件还是其他什么地方 都和它无关。

是由 TemplateRuleBuilder 去做的,而 TemplateRuleBuilder 自然也不用关心规则是怎样的

它只是根据相应的设置构建出一个 TemplateRule

可能你先了解一下单一职责会容易理解些
加载更多回复(7)

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧