实现类选择器的最佳方法

时间:2017-09-01 11:39:03

标签: c# reflection enums

澄清:我没有使用枚举,而是枚举使用哪种方法,而是使用从同一基类驱动的类。因此,用户不会选择使用枚举的方法,而是选择他想要使用的类(通过下拉界面),并且该类包含将被调用的方法的覆盖。在如下所示使其工作之后,我试图在线查看我是否正确行事。这是解决许多问题的方法,但我的问题是我不知道术语来描述它并检查它是否会在将来引起严重问题。

在我使用Enums选择我想要使用的工具之前(枚举工具{brush,eraser,drag})。但是为了使一切更有效而不是使用Enum,我现在为每个工具创建一个类,它导出基本类" 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();
    }
}

这是

的构造函数
public class Family<T> where T : Family<T>

然后我可以

public class newToolBase : Family<newToolBase> {

}

public class eraser:newToolBase {

}

公共类铅笔:newToolBase {

}

我使用Unity和我的意思&#34;选择&#34;通常是从下拉菜单中手动选择内容的选项。如您所见,基类具有名称数组,并在用户选择某些内容时显示。每个可生成的对象,每个AI方法都使用这个类。我只是添加一个派生自Base Class的脚本,该脚本又从Family类中派生出来,可以选择它或添加到列表中。

从下面的评论中我发现了Dependencies Injection并且正在阅读它。我写这篇文章是希望人们能够立即认识到我想要做的事情并指出这样的事情。

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

1 个答案:

答案 0 :(得分:1)

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

MEF代表托管扩展框架 -

  

Managed Extensibility Framework或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();
    }
}

我假设您可以从上面的示例中推断并应用您自己的逻辑。 以上内容可以粘贴到控制台应用程序中,应该可以正常工作。请记住添加正确的参考文献。

这将有助于创建一个非常模块化的应用程序,这将有助于可维护性和可扩展性。 还有其他依赖注入选择,它取决于您的需求。

希望这有帮助。

额外:为了进一步扩展,您只需要初始化MEF容器一次,以便在整个项目中使用它。 我用了ToolTypes = mefContainer.Container.GetExportedValues<ToolType>().ToList(); 但你可以使用

 [ImportMany(typeof(ToolType))]
 public List<ToolType> ToolTypes { get; set; }

或者如果只有一个

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