程序中有如下结构:
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);
}
}
另外,这种利用反射对性能影响大不大?
不知道我这样说,大家有没有看明白的
1. 抽象出一个 接口,IClass 一个方法methodName,其他Class1...2去实现接口
2. 根据类目反射或者传type创建实例 pulic IClass LoadClass(string classname)
1、如果你想知道,不如搜索一下 C#反射,自己试着写几段代码,就可以大概了解怎么写你这个需求了。
说简单也是很简单的,也就两三句代码就可以实现基本需求。
2、性能问题泛泛而谈根本没有用。你得看这个慢在整个操作过程中所占的比例,你操作要1秒还是1小时还是一天。
建个三峡大坝几十年,这个慢啊,多么影响国民经济。
为啥不随便找个人用手摇发电,多快。
或者简单的说,你这样问的情况,反射的性能都不是问题。
你写的代码造成的性能问题影响更大。别伤心,这话对很多人是适应的,包括编程5年10年的老手。
如果你用来反射的处理进程对性能要求极苛,几个毫秒都不能等的话,建议还是放弃使用C#,
把这部分的代码外包给C++做好点,或者烧个片子,调用汇编合适一些。
发现大叔对性能问题有怨念...
@幻天芒: 我们讨论技术哈,跟大神学习
@幻天芒: 大叔是先实现后优化
@beggar_: 用接口哇~工厂方法~
@幻天芒: 被你发现了,灭口的人已经在路上了,你等着被查水表吧。
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不用反射。
@幻天芒: 接口编程。需要动态注入吧,流程就是读取配置文件,反射,注入。
这个也用了反射的,只是Autofac/Ninject/Unity 们多做了一件事,缓存。
也就是说第一次调用一样慢(其实不慢,只是相对慢),后面调用才会快的。
如果需要第一次调用也快的话,也行,预热。(其实第一次还是慢,就是预热)
用户感觉到的已经是第二次了。
@爱编程的大叔: 正是如此,哈哈。如果是Web的应用程序启动,用户基本是无法感知的。所以,有何影响呢。我就不纠结反射的性能。又不是每次调用都要反射,而且就算是反射,性能也查不到哪儿去,优化下页面代码和做下相关的Web优化,效果更好。
@幻天芒: 如果是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毫秒。
@爱编程的大叔: 在后端处理时间相差不大的情况下,优化前端更有意义。
@幻天芒: 对头,因为200MS只是一个基准数字,写得好写得不好,
可能是100毫秒~800毫秒的差别,你优化了半天,多花了3个月开发时间用ADO.NET而不用EF,
结果只要一个稍微不用心的前端(可能还是高手),就可以把省下的时间全部浪费了。
优化性能要找对地方,通常等到需要优化反射或者EF性能的时候,你的工资应该已经超过百万年薪了。
@爱编程的大叔: 确实如此,关于问题本身,直接Ioc就行。
因为各个类里面是处理的不同的业务,只是类名不同,方法都一样,具体的方法里面跟据当前所在的状态来做具体的业务
为什么不提出共同的封装一下呢
最好不要用类名来做。我一般的做法是通过枚举来做“路由”。
枚举是知道范围才能用吧,我现在做的是每个类相当于一个流程,每增加一个流程,就增加一个类,该类是实现该流程下的业务
所以类的命名我是以流程的唯一号来命名的,在调用时先找到流程的唯一号,再根据唯一号来实例调用实现的业务类
@beggar_: 如果是不需要与系统的其它部分匹配的话,直接像楼下那样做就可以了。
我理解应该是个策略模式吧
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; } } }
简单工厂就行了,通过className 创建不同的实例