C# 实现类选择器的最佳方法

C# 实现类选择器的最佳方法,c#,reflection,enums,C#,Reflection,Enums,澄清一下:我使用的不是enum,enum告诉我们使用哪个方法,而是从同一个基类派生的类。因此,用户将选择一个他想要使用的类(通过下拉界面),而不是使用enum选择一个方法,并且该类包含将被调用的方法的重写。在完成如下所示的工作后,我试着上网看看自己是否做对了。这是一种解决很多问题的方法,但我的问题是,我不知道用什么术语来描述它,也不知道它是否会在将来导致严重的问题 在使用枚举选择要使用的工具之前(枚举工具{笔刷、橡皮擦、拖动})。但是为了使一切都更加高效,而不是使用Enum,我现在为派生trom

澄清一下:我使用的不是enum,enum告诉我们使用哪个方法,而是从同一个基类派生的类。因此,用户将选择一个他想要使用的类(通过下拉界面),而不是使用enum选择一个方法,并且该类包含将被调用的方法的重写。在完成如下所示的工作后,我试着上网看看自己是否做对了。这是一种解决很多问题的方法,但我的问题是,我不知道用什么术语来描述它,也不知道它是否会在将来导致严重的问题

在使用枚举选择要使用的工具之前(枚举工具{笔刷、橡皮擦、拖动})。但是为了使一切都更加高效,而不是使用Enum,我现在为派生trom基类“ToolType”的每个工具创建一个类。然后,我使用反射查找从ToolType继承的所有类,并将它们放置在静态数组中。现在我在我的项目中的大部分内容都使用了这个方法,添加/删除内容很容易,无需每次添加新类时都编辑枚举数组。这感觉像是模块化项目的最佳解决方案,但我还没有找到任何这样的例子,所以我不确定我是否用正确的方式来做。我应该找什么

 static Family ()  {
    List<Type> allTypes = CsharpFuncs.GetAllChildTypesOf<T>();

    family = new T[allTypes.Count];
    names = new string[allTypes.Count];

    Debug.Log("Creating "+typeof(T).ToString());

    for (int i = 0; i < allTypes.Count; i++)  {
        Debug.Log("Adding " + allTypes[i].ToString());
        T tmp = (T)Activator.CreateInstance(allTypes[i]);
        family[i] = tmp;
        tmp.index = i;
        names[i] = tmp.ToString();
    }
}
静态族(){
List allTypes=CsharpFuncs.GetAllChildTypesOf();
family=新的T[allTypes.Count];
名称=新字符串[allTypes.Count];
Log(“创建”+typeof(T.ToString());
for(int i=0;i
这是的构造函数

public class Family<T> where T : Family<T>
公共类族,其中T:Family
那我就可以

public class newToolBase : Family<newToolBase> {
公共类newToolBase:Family{
}

公共类橡皮擦:newToolBase{

}

公共类铅笔:newToolBase{

}

我使用的是Unity,我所说的“选择”通常是从下拉列表中手动选择某个内容的选项。正如您所看到的,基类有一个名称数组,当用户选择某个对象时会显示这些名称。每个可生成的对象,每个AI方法都使用这个类。我只是添加了一个从基类派生的脚本,而基类又是从Family类派生的,它可以被选择或添加到列表中

从下面的评论中,我发现了依赖项注入,目前正在阅读相关文章。我写这篇文章是希望人们能马上意识到我在做什么,并指出类似的事情


澄清一下,我的方法没有明显的问题,但在花几个小时用这个替换许多枚举之前,我想确定一下。谢谢

我知道你能做什么。也许有更好的方法可以做到这一点,但希望我能给你一个方向的推动

MEF
代表托管扩展性框架-

托管可扩展性框架或MEF是用于创建轻量级可扩展应用程序的库。

要获得非常简单的设置,您需要将
System.ComponentModel.Composition
库添加到项目中

我使用了一个控制台应用程序来演示您的用例。首先,您必须初始化MEF容器

class MefContainer
{
    public CompositionContainer Container { get; }

    public MefContainer()
    {
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); // You can use an AggregateCatalog if you have more than one assembly.

        Container = new CompositionContainer(catalog);

        Container.ComposeParts(this);
    }
}
现在我们已经有了容器类设置,您需要设置工具类

abstract class ToolType // I've used an abstract class here, but you can use interfaces or normal classes.
{
    public virtual void Test()
    {
        Console.WriteLine("Base");
    }
}

[Export(typeof(ToolType)), PartCreationPolicy(CreationPolicy.NonShared)] // Part creation policy is for your lifetime management. NonShared is instanced and Shared would be like a singleton.
class Brush : ToolType
{
    public override void Test()
    {
        Console.WriteLine("Brush");
    }
}

[Export(typeof(ToolType)), PartCreationPolicy(CreationPolicy.NonShared)]
class Eraser : ToolType
{
    public override void Test()
    {
        Console.WriteLine("Eraser");
    }
}

[Export(typeof(ToolType)), PartCreationPolicy(CreationPolicy.NonShared)]
class  Drag : ToolType
{
    public override void Test()
    {
        Console.WriteLine("Drag");
    }
}
现在它在控制台应用程序中使用:

class Program
{
    public static List<ToolType> ToolTypes { get; set; }

    static void Main(string[] args)
    {
        var mefContainer = new MefContainer();

        ToolTypes = mefContainer.Container.GetExportedValues<ToolType>().ToList();

        ToolTypes.First(x => x.GetType() == typeof(Brush))?.Test();
        ToolTypes.First(x => x.GetType() == typeof(Eraser))?.Test();
        ToolTypes.First(x => x.GetType() == typeof(Drag))?.Test();
    }
}
或者如果只有一个

 [Import(typeof(ToolType))]
 public ToolType Tool { get; set; }

你在使用依赖注入吗?例如
Unity
MEF
Ninject
禁忌症:如果需要第二组工具类型怎么办?一个你不想选择的,第一组在哪里…听起来你好像在要求一个,但你没有说明问题出在哪里。选择器?凭什么?按键-字典,按索引-集合。。。还有,为什么当前方法不好的标准是什么?只有怀疑?告诉所有人去死吧,你是程序员,这是你的任务。。。
 [Import(typeof(ToolType))]
 public ToolType Tool { get; set; }