C# 按名称调用类还是选择大小写/开关?
NET,但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
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");