2014年4月8日星期二

关于反射优化的疑问,单次调用时直接反射要快于委托调用反射? - 魔沦殇

本邮件内容由第三方提供,如果您不想继续收到该邮件,可 点此退订
关于反射优化的疑问,单次调用时直接反射要快于委托调用反射? - 魔沦殇  阅读原文»

因为项目中需要用到反射,而单纯反射据说性能很低,所以就想到了优化反射.而关于反射的优化方案园子里面有不少大牛都已经提出来详细的解决方案,这个就不详细说了,想了解的可以具体看这里http://www.cnblogs.com/fish-li/category/453548.html.文章里面提到了通过创建委托来提高反射性能.

既然有了解决方案,那就来吧.

项目中主要用反射来操作对象属性,所以就先不考虑方法的反射了

使用Emit构造委托

1   public delegate object FastGetMethod(object arg);//定义委托类型
2   public static class FastReflection
3 {
4 /// <summary>
5 /// 缓存委托集合
6    /// </summary>
7 private static ConcurrentDictionary<string, FastGetMethod> _getMethods = new ConcurrentDictionary<string, FastGetMethod>();
8     public static FastGetMethod FastGetMethod(PropertyInfo property)
9 {
10 FastGetMethod getMethod;
11 if (!_getMethods.TryGetValue(string.Concat(property.DeclaringType.FullName, "_", property.Name), out getMethod))
12 {
13 getMethod = FastReflection.GetGetMethod(property);
14 _getMethods.TryAdd(string.Concat(property.DeclaringType.FullName, "_", property.Name), getMethod);
15 }
16 return getMethod;
17 }
18     private static FastGetMethod GetGetMethod(PropertyInfo property)
19 {
20 if (property == null)
21 {
22 throw new ArgumentNullException("property");
23 }
24 if (!property.CanRead)
25 {
26 return null;
27 }
28 MethodInfo method = property.GetGetMethod(true);
29 DynamicMethod dm = new DynamicMethod("GetValueMethod", typeof(object), new Type[] { typeof(object) }, property.DeclaringType, true);
30 ILGenerator il = dm.GetILGenerator();
31 if (!method.IsStatic)
32 {
33 il.Emit(OpCodes.Ldarg_0);
34 il.EmitCall(OpCodes.Callvirt, method, null);
35 }
36 else
37 {
38 il.EmitCall(OpCodes.Call, method, null);
39 }
40 if (property.PropertyType.IsValueType)
41 {
42 il.Emit(OpCodes.Box, property.PropertyType);
43 }
44 il.Emit(OpCodes.Ret);
45 return (FastGetMethod)dm.CreateDelegate(typeof(FastGetMethod));
46 }
47 }

如此,就来测试一下吧
测试代码如下

class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

//调用代码
Person p = new Person() { Age = 100, Name = "Hello Test" };
PropertyInfo info
= (typeof(Person)).GetProperty("Age");
int times = 100 * 100 * 100;//
优雅就一个字――设计模式之数据上传接口 - Sago  阅读原文»

在网上看到很多关于设计模式的文章。但是基本都是单独讲解某一个设计模式的应用场景和设计思路。可是真实的项目中,可能仅仅只按照书上的某种设计模式就能写出优雅的代码吗?我觉得是不可能的。我这篇文章希望跟大家分享的是我思考的过程,而非结果。首先,应该对书上的20多种的设计模式有了解,大概清楚它们都是怎么样一个设计思路。建议有想学习设计模式的Friends还是买本纸质书系统的学习。下面,我给出一个真实的项目来引出我对这个项目的思考。第一次写博客分享我的思路,在加上我的思维有些女性思维,是跳跃性的。可能有些表达不是很清楚。望大家见谅。

    • 看到这流程图,首先在我脑海里的就是这是由一个一个小方块组合起来的组合体。我们先不管具体代码该怎么写,类怎么设计。只知道这是一个组合体。会有很多类。说到组合,我们是否可以联想到这应该是一个结构型的设计。这个组合体是由这些小方块代表的类按照某种结构组合起来的。结构型的设计模式有哪些,大家脑海里应该会有个轮廓了。
    • 又看到每一个小方块有分支,2个分支,分别代表正确的时的下一个流程和不正确时的下一个流程。这是不是意味着,我的方法会一层一层往下调用,直到最后一个小方块对象的下个流程对象为null时停止。想到这,我脑海里想到了装饰者模式和职责链模式。可是装饰者模式没有判断条件,它只是按照你组合的顺序,依次往下调用。那么这是不是更加符合职责链模式呢?咋一看很像,职责链模式是在一个流程内,没有处理的权限就往后传递,有处理权限就跳出方法链。跟我们的2个分支有些不同。我们的需求是要既有权限处理往后传递,没有权限也要往后传递。想到这,我们就清楚了,在小方块所代表的类里,应当有两个属性,一个是判断条件为True时的下一流程对象,另一个是判断条件为False时下一流程对象。这样,小方块类的类结构里就有了两个属性了。
      1. 每个小方块都有两个属性,我们是否就应该有个规范呢?所以我们定义一个接口,让所有的小方块代表的类实现这个接口。接口里目前有两个属性。
    • 接着又想,每个小方块代表的类,所执行的具体业务逻辑不一样,所以,我们在接口里是否应该有个方法可供子类重写呢?这样一来,每个小方块所代表的类都有了自己的业务逻辑。但是,那在什么地方调用下个流程的业务逻辑呢?如果放在单独的每个小方块所代表的类中,那岂不是,我们在每一个小方块类中都要写一些重复的调用下个流程的代码呢?这样就不够优雅了。所以,我想要调用过程在父级类里实现。为了实现小方块类的多态和调用下个流程的代码复用,就有了一个能够有方法实现的类。这个类又必须包含抽象方法。那所有流程的抽象基类出来了。这个抽象类实现之前定义的接口。其实这个接口要不要都无所谓啦,不过好像每个设计模式都是从接口开始,那么就保留一个接口吧。
    • 抽象类有了,每个子类重写的业务逻辑方法也有了。接下来,就是写调用被重写的业务逻辑的方法了。此处,大家应该可以想到是一个模板方法吧。但是,我们这里有两个分支,具体调用哪一个分支是由当前的小方块类决定的。这样一想,那这个调用下个小方块类的业务逻辑方法的代码岂不是只能写在具体的每个小方块类里了。这样不是很麻烦吗?我们要想一个办法,将这个过程放在抽象类里解决。鉴于最多也就两个分支,不是正就是反。那么我们是否可以通过在抽象类里设置一个属性,来标识下一流程具体调用的是哪一个分支呢?所以我们抽象类里又有了一个属性。这个属性是要被子类在业务逻辑方法中重新赋值的。
      1. 在抽象类的调用下一流程的方法里,我们会有一个判断,判断这个属性所代表的下一流程具体是哪一个分支。
    • 当某些业务处理完之后,可能就直接要结束整个流程,比如说,如果我第一步验证没通过,那么后面的流程都不能被执行。所以,我们要能够随时退出整个流程。这样,我们跟上面决定调用哪个分支的设计思路一致,加一个属性,来标识说是否要结束整个流程。可供子类重新赋值。在父类的调用下一个流程的方法中做判断。
  • 那现在我们的抽象类里就有了3个属性,2个方法。
    1. 当条件判断为True时的下一流程属性
    2. 当条件判断为False时的下一流程属性
    3. 标识下一流程调用哪一个分支的属性
    4. 标识是否结束整个流程的属性
    5. 封装了调用过程的方法
    6. 需要被重写的的具体业务逻辑方法
  • 然后,总有参数要传递到每一个小方块类的业务逻辑方法中吧。那么我们这里就将所有参数封装成一个数据实体类。依次传递到每个小方块类的业务逻辑方法中。大概思路就说到这吧。还有一些业务需求没有讲到,那在代码里都有体现。先上代码吧。

/// <summary>
/// 处理流程基类
/// </summary>
public abstract class ProcessFlowBase : IProcessFlow
{
protected ProcessFlowBase(ProcessFlowBase processFlowWhenRight = default(ProcessFlowBase), ProcessFlowBase processFlowWhenWrong = default(ProcessFlowBase))
{
this.NextProcessFlowWhenRight = processFlowWhenRight;
this.NextProcessFlowWhenWrong = processFlowWhenWrong;
this.IsRight = true;
this.IsEnd = false;
}

protected IDbConnection DbConnection { get; set; }

protected IDbCommand DbCommand { get; set; }

protected IDbTransaction DbTransaction { private get; set; }

/// <summary>
/// 当前流程是否处理通过
/// </summary>
private bool IsRight { get; set; }

/// <summary>
/// 流程是否结束
/// </summary>
private bool IsEnd { get; set; }

/// <summary>
/// 下一个流程,当流程处理操作通过的时候
/// </summary>
private ProcessFlowBase NextProcessFlowWhenRight { set; get; }

/// <summary>
/// 下一个流程,当流程处理操作不通过的时候
/// </summary>
private ProcessFlowBase NextProcessFlowWhenWrong { get; set; }

/// <summary>
/// 处理
/// </summary>
/// <param name="dataContext"></param>
public void Process(DataContext dataContext)
{
this.ProcessTemplate(dataContext);
this.RecordLog(dataContext);
if (this.IsEnd) return;
if (this.IsRight)
{
if (this.NextProcessFlowWhenRight == default(ProcessFlowBase)) return;
this.NextProcessFlowWhenRight.SetParameters(this.DbConnection, this.DbCommand, this.DbTransaction);
this.NextProcessFlowWhenRight.Process(dataContext);
}
else
{
if (this.NextProcessFlowWhenWrong == default(ProcessFlowBase)) return;
this.NextProcessFlowWhenWrong.SetParameters(this.DbConnection, this.DbCommand, this.DbTransaction);
this.NextProcessFlowWhenWrong.Process(dataContext);
}
}

/// <summary>
/// 流程处理模板方法,供子类实现
/// </summary>
/// <param name="dataContext"></param>
protected abstract void ProcessTemplate(DataContext dataContext);

/// <summary>
/// 记录日志,供子类实现
/// </summary>
/// <param name="dataContext"></param>
protected virtual void Record

阅读更多内容

没有评论:

发表评论