首页 新闻 会员 周边 捐助

C#设计模式请教 类名做参数

0
悬赏园豆:5 [已解决问题] 解决于 2015-12-07 16:46

程序中有如下结构:

public class class1

{

  public static methodName(int step)

  {

    if(step==1)

    {do.....}

    

    if(step==2)

    {do.....}

  }

}

public class class2

{

  public static methodName(int step)

  {

    if(step==1)

    {do.....}

    

    if(step==2)

    {do.....}

    if(step==3)

    {do.....}

  }

}

因为各个类里面是处理的不同的业务,只是类名不同,方法都一样,具体的方法里面跟据当前所在的状态来做具体的业务。

所以想在知道某个类是处理某个业务的情况下,想把类名做为参数,利用反射的机制去调用,只知道思路,但不知道代码怎么实现,求大神指点

调用的思路:

public class A

{

  pulic void LoadClass(string classname)

  {

    classname.methodName(1);

  }

}

 

另外,这种利用反射对性能影响大不大?

不知道我这样说,大家有没有看明白的

beggar_的主页 beggar_ | 初学一级 | 园豆:10
提问于:2015-11-10 17:05
< >
分享
最佳答案
0

1. 抽象出一个 接口,IClass   一个方法methodName,其他Class1...2去实现接口

2. 根据类目反射或者传type创建实例  pulic IClass LoadClass(string classname)

收获园豆:5
Qlin | 老鸟四级 |园豆:2403 | 2015-11-11 09:56
其他回答(6)
0

1、如果你想知道,不如搜索一下 C#反射,自己试着写几段代码,就可以大概了解怎么写你这个需求了。

说简单也是很简单的,也就两三句代码就可以实现基本需求。

 

2、性能问题泛泛而谈根本没有用。你得看这个慢在整个操作过程中所占的比例,你操作要1秒还是1小时还是一天。

建个三峡大坝几十年,这个慢啊,多么影响国民经济。

为啥不随便找个人用手摇发电,多快。

 

或者简单的说,你这样问的情况,反射的性能都不是问题。

你写的代码造成的性能问题影响更大。别伤心,这话对很多人是适应的,包括编程5年10年的老手。

 

如果你用来反射的处理进程对性能要求极苛,几个毫秒都不能等的话,建议还是放弃使用C#,

把这部分的代码外包给C++做好点,或者烧个片子,调用汇编合适一些。

爱编程的大叔 | 园豆:30844 (高人七级) | 2015-11-10 17:23

发现大叔对性能问题有怨念...

支持(0) 反对(0) 幻天芒 | 园豆:37205 (高人七级) | 2015-11-10 17:24

@幻天芒: 我们讨论技术哈,跟大神学习

支持(0) 反对(0) beggar_ | 园豆:10 (初学一级) | 2015-11-10 17:30

@幻天芒: 大叔是先实现后优化

支持(0) 反对(0) jello chen | 园豆:7336 (大侠五级) | 2015-11-10 17:33

@beggar_: 用接口哇~工厂方法~

支持(0) 反对(0) 幻天芒 | 园豆:37205 (高人七级) | 2015-11-10 22:34

@幻天芒: 被你发现了,灭口的人已经在路上了,你等着被查水表吧。

Demo,

1、假设反射需要10MS, 功能代码1MS。

测试都是这样进行的10+1,运行10万次,然后告诉你速度变慢了10倍。

 

然而真实的世界是,程序员这样写代码,会被打死的。

肯定是10+1*100000≈1*100000,反射根本不影响性能。

 

2、反射10MS,功能代码100MS,这个就更加不是问题了。

 

这个是工业界TCO(Total Cost of Ownership)的概念,要记住反射只是你

所有性能成本环节中的一个小环节。

通常大部分场景下,整体运行成本都是远超过反射的,除非少数特定的操作。

EF也是类似的情况。

在特定的场景下,你懂得EF,懂得反射,你仍然可以返回使用ADO使用汇编,使用C++的。

不要被性能这个指标坑了就不用EF不用反射。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2015-11-11 09:30

@幻天芒: 接口编程。需要动态注入吧,流程就是读取配置文件,反射,注入。

这个也用了反射的,只是Autofac/Ninject/Unity 们多做了一件事,缓存。

也就是说第一次调用一样慢(其实不慢,只是相对慢),后面调用才会快的。

如果需要第一次调用也快的话,也行,预热。(其实第一次还是慢,就是预热)

用户感觉到的已经是第二次了。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2015-11-11 11:07

@爱编程的大叔: 正是如此,哈哈。如果是Web的应用程序启动,用户基本是无法感知的。所以,有何影响呢。我就不纠结反射的性能。又不是每次调用都要反射,而且就算是反射,性能也查不到哪儿去,优化下页面代码和做下相关的Web优化,效果更好。

支持(0) 反对(0) 幻天芒 | 园豆:37205 (高人七级) | 2015-11-11 11:14

@幻天芒: 如果是WEB更加没有问题了,网页从服务器传到浏览器都好几百毫秒了,我还没说一个网页打开要几秒的呢。这就是TCO。

类似的, EF的TCO是。

1、数据请求, EF:10MS, ADO.NET:1MS (真实情况还没有差别这么大)

2、Razor 解释,表格填充, 30MS,或者WEBAPI序列化为JSON数据, 10MS

3、互联网传送到浏览器,80MS

4、浏览器接收WEBAPI JSON数据,JAVASCRIP渲染表格, 200MS

这样总的时间是10MS+10MS+80MS+200MS=300MS,使用ADO.NET,291毫秒。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2015-11-11 11:30

@爱编程的大叔: 在后端处理时间相差不大的情况下,优化前端更有意义。

支持(0) 反对(0) 幻天芒 | 园豆:37205 (高人七级) | 2015-11-11 11:57

@幻天芒: 对头,因为200MS只是一个基准数字,写得好写得不好,

可能是100毫秒~800毫秒的差别,你优化了半天,多花了3个月开发时间用ADO.NET而不用EF,

结果只要一个稍微不用心的前端(可能还是高手),就可以把省下的时间全部浪费了。

优化性能要找对地方,通常等到需要优化反射或者EF性能的时候,你的工资应该已经超过百万年薪了。

支持(0) 反对(0) 爱编程的大叔 | 园豆:30844 (高人七级) | 2015-11-11 12:07

@爱编程的大叔: 确实如此,关于问题本身,直接Ioc就行。

支持(0) 反对(0) 幻天芒 | 园豆:37205 (高人七级) | 2015-11-11 14:59
0

因为各个类里面是处理的不同的业务,只是类名不同,方法都一样,具体的方法里面跟据当前所在的状态来做具体的业务

 为什么不提出共同的封装一下呢

jello chen | 园豆:7336 (大侠五级) | 2015-11-10 17:29
0

最好不要用类名来做。我一般的做法是通过枚举来做“路由”。

吴瑞祥 | 园豆:29449 (高人七级) | 2015-11-11 09:42

枚举是知道范围才能用吧,我现在做的是每个类相当于一个流程,每增加一个流程,就增加一个类,该类是实现该流程下的业务

所以类的命名我是以流程的唯一号来命名的,在调用时先找到流程的唯一号,再根据唯一号来实例调用实现的业务类

支持(0) 反对(0) beggar_ | 园豆:10 (初学一级) | 2015-11-11 15:35

@beggar_: 如果是不需要与系统的其它部分匹配的话,直接像楼下那样做就可以了。

支持(0) 反对(0) 吴瑞祥 | 园豆:29449 (高人七级) | 2015-11-12 09:25
0

你讲到了设计模式,我比较看好 @jello chen ,与@Qlin 的,jello chen说的封装你可以试试,Qlin其实比较接近适配器模式,你自己也可以试试

稳稳的河 | 园豆:4216 (老鸟四级) | 2015-11-11 11:01
0

我理解应该是个策略模式吧

namespace DesignPattern
{
    public class CashContext
    {
        public CashSuper cs = null;
        private string Type;
        public CashContext(string Type, object[] parameters)  
        {  
            //应用反射将原来的switch语句去掉  
            this.Type = Type;
            cs = (CashSuper)Assembly.Load("DesignPattern").CreateInstance("DesignPattern." + this.Type,
                true,System.Reflection.BindingFlags.Default,null,parameters,null,null);  
        }
        public CashContext(CashSuper cs)
        {
            this.cs = cs;
        }
        public double GetResult(double money)
        {
            return cs.acceptCash(money);
        }
    }
}
namespace DesignPattern
{
    /* 策略模式
    应用场景:
    1、 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。
    2、 需要在不同情况下使用不同的策略(算法),或者策略还可能在未来用其它方式来实现。
    3、 对客户隐藏具体策略(算法)的实现细节,彼此完全独立。
     */
    class Strategy
    {
    }
    /// <summary>  
    /// 现金收取父类,算法的抽象类  
    /// </summary>  
    public abstract class CashSuper
    {
        /// <summary>  
        /// 抽象方法:收取现金  
        /// </summary>  
        /// <param name="money">原价</param>  
        /// <returns>当前价</returns>  
        public abstract double acceptCash(double money);
    }
    /// <summary>  
    /// 正常收费  
    /// </summary>  
    public class CashNormal : CashSuper
    {
        public override double acceptCash(double money)
        {
            return money;
        }
    }  
    /// <summary>  
    /// 打折收费  
    /// </summary>  
    public class CashRebate : CashSuper
    {
        private double moneyRebate = 1d;

        public CashRebate(string money)
        {
            this.moneyRebate = double.Parse(money);
        }

        //初始化时必需输入折扣率,如八折就是0.8  
        public override double acceptCash(double money)
        {
            return money * moneyRebate;
        }
    }
    /// <summary>  
    /// 返利收费  
    /// </summary>  
    public class CashReturn : CashSuper
    {
        private double moneyCondition = 0.0d;
        private double moneyReturn = 0.0d;

        /// <summary>  
        /// 初始化时必须要输入返利条件和返利值,比如满300返100,则moneyCondition为300,moneyReturn为100  
        /// </summary>  
        /// <param name="moneyCondition"></param>  
        /// <param name="moneyReturn"></param>  
        public CashReturn(string moneyCondition, string moneyReturn)
        {
            this.moneyCondition = double.Parse(moneyCondition);
            this.moneyReturn = double.Parse(moneyReturn);
        }

        public override double acceptCash(double money)
        {
            double result = money;
            //若大于返利条件,则需要减去返利值  
            if (money >= moneyCondition)
            {
                result = money - Math.Floor(money / moneyCondition) * moneyReturn;
            }
            return result;
        }
    }  
}

demo:http://download.csdn.net/detail/charles809/8941855

clarlespeng | 园豆:469 (菜鸟二级) | 2015-11-11 11:13
0

 简单工厂就行了,通过className 创建不同的实例

xmj112288 | 园豆:126 (初学一级) | 2015-11-12 09:33
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册