按名称调用类或选择案例/开关?

时间:2017-08-25 19:06:29

标签: c# vb.net reflection

VB.NET,但C#也可以。

我有一个/** @var \DateTime $row[$key]['new'] */ 基类和170个基于它的继承类。为什么这么多?因为每个继承的类在MustInherit中执行不同的操作。继承的类型不添加任何新属性,但具有不同的私有字段。它们只是以不同方式处理不同的已知变量集。所以想这样:

Sub New()

实际上,Public MustInherit Class Base Public Property Width End Class Public Class Child1 Inherits Base Private z as Integer = 7 Public Sub New(x as integer) Width = 20 * x * 7 End Sub End Class Public Class Child170 Inherits Base Private y as Integer = 4 Public Sub New(x as integer) Width = 5 * x / y End Sub End Class 中的内容是基于发送内容的大量处理指令(例如Sub New)。这些处理指令将使用位于继承类中的大量私有变量。

另外,我会根据一个名为X as Integerchild1的字符串变量知道我需要创建哪个子项。

所以,有这么多继承的孩子,这里最好的方法是什么(最快,最短的写作量,最佳表现等)。

选项:

  1. 使用child170来调用并创建170个不同类别中的一个,例如:

    Select Case
  2. 以某种方式反映了我创建一个通用的假(伪,因为我对此不太了解):

    Dim b as Base 
    Select Case childName
       Case "child1"
         b = New Child1(x)
       Case "child74"
         b = New Child74(x)
       Case "child103"
         b = New Child103(x)
    End Select
    

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

  3. 还有别的吗?

  4. 欢迎任何帮助/建议/最佳实践(除了那些说“为什么你需要170件事?不要使用170件事”)。

3 个答案:

答案 0 :(得分:3)

您可以使用反射来构建Dictionary<string/Type>实例。用它来根据字符串名称实例化正确的类型。您可以将字符串比较器传递给键/查找,因此它不区分大小写。在应用程序的生命周期中仅构建字典1x(在某些Factory类的静态字段中保留它)。

这是用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 { }
}

致电代码

var factory = new Factory();
var child1 = factory.Create("child1");

答案 1 :(得分:2)

我们都喜欢拥有最快,最短的写作量,最佳性能和#34;选项,但通常需要权衡,你必须选择一个!

&#34;最佳表现&#34;选项可能是tz = "",但编写时间会更长,如果添加新类,则需要持续维护。

&#34;写入的最短金额&#34;选项可能是使用反射。它只需要几行代码,并且可以自我维护。像这样的东西可以解决这个问题:

Select Case

我的建议是尝试一下,看看它是否符合您的预期 - 如果您创建了大量实例,它可能不会,但如果您一次创建一些,它将会可能没事。如果性能有问题,那么Select Case会更快。

当然反思中有许多仇恨者会告诉你永远不要使用它......如果你意识到潜在的性能问题,你可以做出明智的决定。

答案 2 :(得分:1)

坚持你的脚注,我会把它做成1和2的组合。

Dim b as Base

'Type.GetType may not work in all scenarios
Dim childType As Type = Type.GetType(childName, true, true)

Select Case childType
    'Specific implementations
    Case GetType(ProblemChild)
        b = New ProblemChild(x, y, z)
    Case Else
        b = DirectCast(Activator.CreateInstance(childType, x), Base)
End Select

这将允许您根据名称获取类型(请注意,您可能需要将命名空间和可能的其他信息提供给它)。现在您已经拥有了类型,我们可以利用VB.NET的能力来关闭类类型(C#现在也可以这样做)。

任何特殊的实现都可以在Select中明确定义它们的东西,而其他只需要相同标准构造函数参数的东西可以留给Activator

对不起,如果它不能立即编译,VB有点生锈。