Don't think you are, know you are

博客园 首页 新随笔 管理


上一篇说了 abstract factory 和简单工厂,下面简单介绍一下反射工厂。

先说一下反射技术吧,看下面2段代码:

// The conventional way to call an object
businessObject bo=new businessObject();
bo.DoWork();

//The .net reflection way to call a object
Assembly assm=Assembly.Load("TestApp");
Type objType=assm.GetType("TestApp.BusinessObject");
object objInstance=Activator.CreateInstance(objType);
objType.InvokeMember("DoWork",BindingFlags.InvokeMethod,null,objInstance,null)

以上是功能完全相同的2段代码,前一段是普通的类的方法的调用,后一段是用反射写成的。注意后一个代码段中所有的类名方法名都是字符串,所以我们可以使用在运行时刻赋值的字符串变量,来代替硬编码的字符串。这样,就避免了应用直接依赖于特定的具体类。将指定具体类推迟到了运行时刻。

顺便也说一下反射的缺点,如果使用了错误的类名或方法名,编译器是无法识别错误的,只有在运行时才能看到错误。另外,IDE环境下的智能感应也无法为你服务了。

OK,继续。

反射中的类或者方法既然都是字符串,那我们是多么方便的使用配置文件储存这些信息。在我们替换工厂或者类时,只需要更改配置文件就可以了。

示意代码如下:(抽象工厂)
客户端:
ProductFactory pf;
pf=ClassFactory.GetFactory("ProducFactoryA");
Product cheapProduct=pf.GetCheapProduct();
Product.RaisePrice()


Class Factory 的GetFactory方法(反射)
{
public static object GetFactory(string factoryName)
{
 object factory=null;
xmlNode classFactoryData=ConfigurationSettings.GetFactoryData(factoryName);
string type=classFactoryData.attributes["type"].Value;
Type t=System.Type.GetType(type);

factory=Activator.CreateInstance(t,null);
return factory;
}
}
配置文件

<Class name="ProductFactoryA" type="OneConcreteProductFactory">

OneConcretePRoductFactory   是程序集中继承了ProductFactory 的具体类。

如果那天需要替换为 NewConcreteProductFactory, 只需要创建好NewConcreteProductFactory后,在配置文件改一下就可以了。其他地方的代码一点都不用动。



再介绍反射工厂的另一种用法:前面已经提到过,面向接口编程是优秀的编程方法。在不new一个具体类的情况下使用接口,除了使用类工厂外,我们还可以使用反射的方法,“自动”找到程序集中实现接口的具体类,进而使用它。

                Dim testAssembly As System.Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly
                For Each type In testAssembly.GetTypes()
                    If Not type Is Nothing AndAlso Not type.IsAbstract AndAlso GetType(AbstractClassBase).IsAssignableFrom(type) Then
                        Dim test As AbstractClassBase
                        test = CType(Activator.CreateInstance(type), AbstractClassBase)
                        currentTest = test
                        If args.Length > 0 Then
                            Try
                                test.HandleCommandLineArguments(args)
                            Catch ex2 As Exception
                                System.Console.WriteLine(ex2.ToString())
                                System.Diagnostics.Trace.WriteLine(ex2.ToString())
                                'Exit Sub
                            End Try
                        End If
                 test.Execute()
              Next

AbstractClassBase 是一个抽象类
test 是我们获得的事先不知道的程序集中的具体类
 System.Reflection.Assembly.GetExecutingAssembly 获取当前程序集
Type.IsAssignableFrom (c) 的返回值
true if c and the current Type represent the same type, or if the current Type is in the inheritance hierarchy of c, or if the current Type is an interface that c implements, or if c is a generic type parameter and the current Type represents one of the constraints of c
呵呵,这么简单的英文就不翻译了。
好用吧。

posted on 2007-07-15 14:13  炭炭  阅读(313)  评论(0编辑  收藏  举报