假设有一个abstract基类:
abstract class BaseClass
{
    public abstract string Name { get;}
}然后由它继承得到若干派生类:
class D1 : BaseClass
{
    public override string Name { get { return "D1"; } }
}
class D2 : BaseClass
{
    public override string Name { get { return "D2"; } }
}
/* D3,D4,... */现在需要一个函数,根据参数中给出的类的名字构造对应的派生类对象。它的代码可能像下面这样:
BaseClass CreateInstance(string ClassName)
{
    switch (ClassName)
    {
        case "D1": return new D1();
        case "D2": return new D2();
        /* D3,D4,... */
    }
    return null;
}由于派生类比较多,如果用switch来写,代码的输入和调试都将成为不小的负担。现在请问,是否有一种方法简化这个CreateInstance函数?我想,我需要的函数可能像下面这个样子(伪代码表示)
BaseClass CreateInstance(string ClassName)
{
    Type[] types = BassClass的所有派生类的Type;
    foreach(Type t in types)
    {
        string s = 一个t类型的实例的Name属性值;
        if( s == ClassName )
            return 一个t类型的实例;
    }
    return null;
}以前C++中我也想过类似问题,但当时没能解决。感觉C#的反射机制功能很多,不知道能否实现?
望各位指点,小弟谢过。

解决方案 »

  1.   

    先用Assembly读入一个程序集
    从程序集取得所有属于class的type
    再判断type中你需要的名称然后构造,转化成父类型返回就行了。
    在一本C#的设计模式的书里,这个叫:“反射工厂”本人不建议这么做。创建型模式那么多,根据具体的应用应该有更好的选择。
      

  2.   

    C#反射轻松实现
    示例 
    using System;
    using System.Reflection;
    public class LoadInvoke
    {
        public static void Main(string[] args)
        {
            Assembly a = Assembly.LoadFrom(args[0]);
            Type[] mytypes = a.GetTypes();
            BindingFlags flags = (BindingFlags.NonPublic | BindingFlags.Public | 
                BindingFlags.Static | BindingFlags.Instance | BindingFlags.DeclaredOnly);        foreach(Type t in mytypes)
            {
                MethodInfo[] mi = t.GetMethods(flags);
                Object obj = Activator.CreateInstance(t);            foreach(MethodInfo m in mi)
                {
                    m.Invoke(obj, null);
                }
            }
        }
    }
      

  3.   

    或者直接看看.net framework SDK
    《反射, 动态使用类型》
      

  4.   

    根据具体的应用应该有更好的选择
    ===================================
    谢谢你的建议。
    我也是这样想的,以前C++遇到这个问题时我就换了思路绕过去了。但现在新学C#,是出于好奇才想这样做的。本来这也不是什么大的工程项目,练习而已。
    我已经照着Eddie005()的代码自己写了一个:
    public static Skill Parse(string SkillName)
    {
        Type SkillType = typeof(Skill);
        Assembly a = Assembly.GetAssembly(SkillType);
        Type[] types = a.GetTypes();
        foreach (Type t in types)
        {
            if (t.IsAbstract || !t.IsSubclassOf(SkillType))
                continue;
            Skill skill = (Skill)Activator.CreateInstance(t);
            if (skill.Name == SkillName)
                return skill;
        }
        throw new Exception("没有合适的技能");
    }
    由于Skill的各个派生类都只有一个Int32类型的成员,所以构造对象的代价并不大,我想在我的程序应该是适合使用的。谢谢几位了。
    (大家没新的意见的话,我过段时间就结帖。)
      

  5.   

    就算对象不是很小也一样可以用反射的。只要你没有真正创建一个类的实例,它也不会有多少开销的。.net 项目上的工厂大多不都采用反射工厂吗
      

  6.   

    Skill skill = (Skill)Activator.CreateInstance(t);
    这个已经创建了类的实例了吧?
      

  7.   

    创建几个类的实例的开销应该是可以接受的吧。不管你是 new 出来的还是 create 出来的,效果是一样的啊。.net 本来就吃内存,一个空窗口程序都要吃十几M的内存,几个对象不用太在意的。只管不是非托管对象或稀有资源,早晚会被回收掉。
      

  8.   

    这种问题肯定是用Reflect.所有的具体的类要从一个接口继承而来,程序代码内只需依赖这个接口就成,具体的类名可以通过配置文件得到,可以根据需要动态生成不同的对象.放在配置文件的好处是程序不需要倚赖具体实现组件.