C# 按名称调用类还是选择大小写/开关?

C# 按名称调用类还是选择大小写/开关?,c#,vb.net,reflection,C#,Vb.net,Reflection,NET,但C#也可以 我有一个MustInherit基类和170个基于该基类的继承类。为什么这么多?因为每个继承的类在Sub New()中执行不同的操作。继承的类型不添加任何新属性,但具有不同的私有字段。它们只是以不同的方式处理不同的已知变量集。所以你可以这样想: 公共MustInherit类基类 公共财产宽度 末级 公营儿童1 继承基础 私有z作为整数=7 公共子新建(x为整数) 宽度=20*x*7 端接头 末级 公营儿童170 继承基础 私有y为整数=4 公共子新建(x为整数) 宽度=5*x

NET,但C#也可以

我有一个
MustInherit
基类和170个基于该基类的继承类。为什么这么多?因为每个继承的类在
Sub New()
中执行不同的操作。继承的类型不添加任何新属性,但具有不同的私有字段。它们只是以不同的方式处理不同的已知变量集。所以你可以这样想:

公共MustInherit类基类
公共财产宽度
末级
公营儿童1
继承基础
私有z作为整数=7
公共子新建(x为整数)
宽度=20*x*7
端接头
末级
公营儿童170
继承基础
私有y为整数=4
公共子新建(x为整数)
宽度=5*x/y
端接头
末级
实际上,新的
子文件中的内容是基于发送内容的大量处理指令(例如,
X作为整数
)。这些处理指令将处理位于继承类中的大量私有变量

另外,我将知道需要根据名为相同的字符串变量创建哪个子级,如
child1
child170

那么,有这么多遗传的孩子,这里最好的方法是什么(最快、最短的写量、最好的性能等等)

选项:

  • 使用
    选择Case
    调用并创建170个不同类中的一个,如:

    尺寸b作为基准
    选择Case childName
    案例“儿童1”
    b=新子女1(x)
    案件“儿童74”
    b=新子女74(x)
    “儿童103”案
    b=新子女103(x)
    结束选择
    
  • 以某种方式反映了我创建泛型的呼吁(伪,因为我对此不太了解):

    Dim b as Base=Activator.CreateInstance(Type.GetType(“MyProjectName”和childName))
    
    其中“childName”是170个子项中的一个,然后是
    b.Process(x)
    ——这假设我使用了一个名为
    Process
    的例程,因为我在
    CreateInstance
    中没有看到任何在构造函数中发送值的示例

  • 还有别的吗


  • 欢迎提供任何帮助/建议/最佳实践(除了那些说“你为什么需要170件东西?不要使用170件东西”的人)。

    根据你的脚注,我会结合使用1和2

    尺寸b作为基准
    'Type.GetType可能无法在所有情况下工作
    Dim childType As Type=Type.GetType(childName,true,true)
    选择Case-childType
    '具体实施
    案例GetType(ProblemChild)
    b=新问题儿童(x,y,z)
    其他情况
    b=DirectCast(Activator.CreateInstance(childType,x),基)
    结束选择
    
    这将允许您根据名称获取类型(请注意,您可能需要向其提供名称空间和一些其他信息)。既然您有了这个类型,我们就可以利用VB.NET关闭类类型的功能(C#现在也可以这样做)

    任何特殊的实现都可以在Select中明确定义它们的内容,而其他所有只采用相同标准构造函数参数的实现都可以留给
    激活器

    很抱歉,如果它不能立即编译,VB有点生疏。

    我们都希望有“最快、最短的写入量、最好的性能”选项,但通常这是一种折衷,您必须选择一个

    “最佳性能”选项可能是
    Select Case
    ,但如果添加新类,则需要更长的编写时间和持续的维护

    “最短写入量”选项可能是使用反射。它只需要几行代码,并且可以自我维护。像这样的东西可以达到目的:

    Dim childNames As String()=新字符串(){“Child1”、“Child2”、“Child1”、“Child1”、“Child3”}
    对于每个子对象,将s作为子名称中的字符串
    Dim assm As Assembly=GetType(Child1).Assembly
    将nmspc设置为字符串=“MyNameSpace”
    Dim type As type=assm.GetType(String.Format(“{0}.{1}”,nmspc,s))
    Dim obj As Object=Activator.CreateInstance(类型)
    下一个
    
    我的建议是尝试一下,看看它的性能是否达到您的预期——如果您创建大量实例,它可能不会,但是如果您一次创建几个实例,它可能会很好。如果性能有问题,则选择案例会更快


    当然,反射有很多仇恨者,他们会告诉你永远不要使用它。。。如果您知道潜在的性能问题,您可以做出明智的决定。

    您可以使用反射来构建一个
    字典
    实例。使用它根据字符串名称实例化正确的类型。可以将字符串比较器传递给键/查找,使其不区分大小写。在应用程序的生命周期内只构建一个字典(在某些工厂类中将其保存在静态字段中)

    这是用c#编写的,但您可以将其移植到vb.net

    using System;
    using System.Collections.Generic;
    using System.Linq;
    
    namespace YourNamespace
    {
        public sealed class Factory
        {
            private static readonly Dictionary<string, Type> TypeLookup;
    
            static Factory()
            {
                // You could iterate over additional assemblies if needed
                // the key is assumed to be the name of the class (case insensitive)
    
                TypeLookup = typeof(Factory).Assembly.GetTypes()
                    .Where(t => t.IsClass && !t.IsAbstract && typeof(SomeBase).IsAssignableFrom(t))
                    .ToDictionary(t => t.Name, t => t, StringComparer.OrdinalIgnoreCase);
            }
    
            public SomeBase Create(string name)
            {
                Type t;
                if (TypeLookup.TryGetValue(name, out t))
                {
                    return (SomeBase) Activator.CreateInstance(t);
                }
                throw new ArgumentException("Could not find type " + name);
            }
        }
    
        public abstract class SomeBase { }
        public class Child1 : SomeBase { }
        public class Child2 : SomeBase { }
        public class Child3 : SomeBase { }
    }
    

    Select案例
    显然要快得多。折衷是每次需要添加新名称时都必须修改代码并重新编译。反射所带来的额外开销可能并不重要。而且,尽管你提出了警告,你可能真的做得不对。您的解决方案过于依赖继承。您是否考虑过使用类似于
    ExpandoObject
    的东西?您可以获得所有相同的好处(包括点符号支持),而不会加重继承。@RobertHarvey。我同意-170个类并不理想,因为实际上每个类中只有内部变量(很多)是不同的。我以前没有使用过
    ExpandoObject
    ,我会查找它,看看它是否适合我的场景。谢谢你。这看起来类似于仅使用字符串的
    Select Case
    ,就像我仍然需要创建170个Case一样。那是科雷吗
    var factory = new Factory();
    var child1 = factory.Create("child1");