C# 在C中选择子类而不知道其名称#

C# 在C中选择子类而不知道其名称#,c#,inheritance,plugins,module,subclass,C#,Inheritance,Plugins,Module,Subclass,编辑1:如果有人对此有更好的标题,请随时告诉我或自己编辑。 编辑2:感谢你们的贡献,伙计们,给出的答案几乎就是我所需要的,经过一些调整,我很感谢这里的小东西。今天真的学到了很多 这里的一些小东西,我现在正忙着呢。 我想创建一个幻灯片,并希望在图像对象本身的逻辑 程序应该能够设置所需的转换或只是随机转换,因此 我想用一般的东西创建一个过渡超类,并将其具体化 它包含在子类中。因此我有Transitions.cs(其中当前没有代码) 并且没有派生类。我希望它以添加单个.cs文件的方式进行 扩展Tran

编辑1:如果有人对此有更好的标题,请随时告诉我或自己编辑。
编辑2:感谢你们的贡献,伙计们,给出的答案几乎就是我所需要的,经过一些调整,我很感谢这里的小东西。今天真的学到了很多

这里的一些小东西,我现在正忙着呢。
我想创建一个幻灯片,并希望在图像对象本身的逻辑

程序应该能够设置所需的转换或只是随机转换,因此
我想用一般的东西创建一个过渡超类,并将其具体化
它包含在子类中。因此我有Transitions.cs(其中当前没有代码)
并且没有派生类。我希望它以添加单个.cs文件的方式进行
扩展Transitions.cs,不更改任何其他代码以实现新的转换

我目前拥有的代码看起来像这样,但我猜我的
说明比代码更有用

public class SlideImages : MonoBehaviour {

    Image image;
    Image nextImage;
    int tracker;

    private void Transition(int ID)
    {
        /*Something to choose a transition based on the ID
        *Transitions.cs is the superclass of all different transitions
        *f.e. Ken-Burns Effect, or scattered Transition which all extend from it
        */
    }

    ~SlideImages()
    {
        //TODO: Pop and Push
    }
}
我想到了一些类似于静态的东西来解决这个问题
看起来像这样,但我想它不起作用

public class Transitions : MonoBehaviour {

    public static int TransitionID;
    protected static int SubclassCount;

    protected static void SetID()
    {
        TransitionID = Transitions.SubclassCount;
        Transitions.SubclassCount++;
    }
}
我确实研究了状态设计模式,但我不想实现它,因为我只需要选择一次状态,而且状态是短暂的。图像对象本身的生存期只有几秒钟左右。我不想做通常的嵌套,也不想把所有代码都放在slidemages.cs中。有没有什么好的指南可以深入到继承之类的东西


感谢所有的投入。

对于您想要做的事情,有两个简单的解决方案。您的基本问题是,您希望能够动态地将功能添加到程序中,但不希望为了使用它而知道添加了什么。最老练的方法是使用
操作
而不是子类化。如果要添加另一个转换,只需更新如下操作列表:

public static class Transitions
{
    private static Action[] TransitionStrategies = new Action[]
    {
        () => { /* One way of performing a transition */ },
        () => { /* Another way of performing a transition */ },
        () => { /* Keep adding methods and calling them here for each transition type */ }
    }

    public static void PerformTransition(int? transitionIndex = null)
    {
        int effectiveIndex;

        // if the transition index is null, use a random one
        if (transitionIndex == null)
        {
            effectiveIndex = new Random().Next(0, TransitionStrategies.Length);
        }
        else
        {
            effectiveIndex = transitionIndex.Value;
        }

        // perform the transition
        TransitionStrategies[effectiveIndex]();

    }
}
static void Main(string[] args)
{
    // create a list to hold the transitions we load
    List<AbstractTransition> transitions = new List<AbstractTransition>();

    // load each module we find in the modules directory
    foreach (string dllFilepath in Directory.EnumerateFiles("Modules", "*.dll"))
        // this should really read from the app config to get the module directory                
    {
        Assembly dllAssembly = Assembly.LoadFrom(dllFilepath);

        transitions.AddRange(dllAssembly.GetTypes()
            .Where(type => typeof(AbstractTransition).IsAssignableFrom(type))
            .Select(type => (AbstractTransition) Activator.CreateInstance(type)));
    }

    // show what's been loaded
    foreach (AbstractTransition transition in transitions)
    {
        Console.WriteLine("Loaded transition with id {0}", transition.TransitionId);

        // execute just to show how it's done
        transition.PerformTransition();
    }

    Console.Read(); // pause
}
Loaded transition with id 2
Performing flip transition
Loaded transition with id 1
Performing slide transition
上述方法很简单,但所有逻辑(或至少对逻辑的引用,取决于您在何处实现转换的实际工作)都在一个地方。它也有可能变得相当混乱,这取决于您添加了多少转换,以及有多少开发人员正在接触这个代码库。它还要求有权访问完整代码库的人添加所有功能,并且每次添加新的转换时都需要重新编译

从长远来看,一种更复杂但更易于维护和灵活的方法是使用模块(或插件)。该方法中的每个转换由共享模块或特定模块提供,并且是基本
AbstractTransition
类的子类,或者是
itTransition
接口的实现,具体取决于您希望如何进行转换。使用生成后任务将所有模块DLL放在主程序可访问的单个目录中(任何其他获得权限的人也可以将转换模块DLL放在该目录中)。当您的程序启动时,它会动态加载该目录中的所有DLL(只要正确的DLL在该目录中,添加新转换时无需重新编译),并拉出实现该接口的所有类。这些接口实现中的每一个都被实例化并放置到一个数据结构中,之后您可以使用与上面的
PerformTransition
方法类似的策略来执行随机的一个或基于ID而不是索引的一个。如果你愿意,我可以用这个结构的例子来编辑这个问题

编辑:你还没有要求它,但这里有一个插件/模块的例子

首先,创建一个项目来加载和运行转换。本例将使用名为
ModuleDemo
的项目。给它一个这样的主要方法:

public static class Transitions
{
    private static Action[] TransitionStrategies = new Action[]
    {
        () => { /* One way of performing a transition */ },
        () => { /* Another way of performing a transition */ },
        () => { /* Keep adding methods and calling them here for each transition type */ }
    }

    public static void PerformTransition(int? transitionIndex = null)
    {
        int effectiveIndex;

        // if the transition index is null, use a random one
        if (transitionIndex == null)
        {
            effectiveIndex = new Random().Next(0, TransitionStrategies.Length);
        }
        else
        {
            effectiveIndex = transitionIndex.Value;
        }

        // perform the transition
        TransitionStrategies[effectiveIndex]();

    }
}
static void Main(string[] args)
{
    // create a list to hold the transitions we load
    List<AbstractTransition> transitions = new List<AbstractTransition>();

    // load each module we find in the modules directory
    foreach (string dllFilepath in Directory.EnumerateFiles("Modules", "*.dll"))
        // this should really read from the app config to get the module directory                
    {
        Assembly dllAssembly = Assembly.LoadFrom(dllFilepath);

        transitions.AddRange(dllAssembly.GetTypes()
            .Where(type => typeof(AbstractTransition).IsAssignableFrom(type))
            .Select(type => (AbstractTransition) Activator.CreateInstance(type)));
    }

    // show what's been loaded
    foreach (AbstractTransition transition in transitions)
    {
        Console.WriteLine("Loaded transition with id {0}", transition.TransitionId);

        // execute just to show how it's done
        transition.PerformTransition();
    }

    Console.Read(); // pause
}
Loaded transition with id 2
Performing flip transition
Loaded transition with id 1
Performing slide transition
现在我们有了一个用于插件实现的抽象转换类和一个功能正常的插件加载程序,我们可以继续创建一些转换插件

我在解决方案中为此创建了一个
Modules
文件夹,但这并不重要

FlipTransition
项目中的第一个模块:

using System;
using TransitionModule;

namespace FlipTransition
{
    public class FlipTransition : AbstractTransition
    {
        public FlipTransition() : base(2)
        {
        }

        public override void PerformTransition()
        {
            Console.WriteLine("Performing flip transition");
        }
    }
}
using System;
using TransitionModule;

namespace SlideTransition
{
    public class SlideTransition : AbstractTransition
    {
        public SlideTransition() : base(1)
        {
        }

        public override void PerformTransition()
        {
            Console.WriteLine("Performing slide transition");
        }
    }
}
SlideTransition
项目中的第二个模块:

using System;
using TransitionModule;

namespace FlipTransition
{
    public class FlipTransition : AbstractTransition
    {
        public FlipTransition() : base(2)
        {
        }

        public override void PerformTransition()
        {
            Console.WriteLine("Performing flip transition");
        }
    }
}
using System;
using TransitionModule;

namespace SlideTransition
{
    public class SlideTransition : AbstractTransition
    {
        public SlideTransition() : base(1)
        {
        }

        public override void PerformTransition()
        {
            Console.WriteLine("Performing slide transition");
        }
    }
}
请注意,这些项目中的每一个都需要引用
TransitionModule
项目,但主项目不需要知道任何其他项目

现在我们有2个转换插件和一个插件加载程序。由于插件加载程序将从
modules
目录加载模块,因此请转到主项目的
/bin/Debug
目录,并创建一个
modules
目录。将转换插件项目的
/bin/Debug
目录中的所有DLL也复制到该目录中。所有这些都可以在以后的构建后任务中实现自动化

继续运行程序。您应该得到如下输出:

public static class Transitions
{
    private static Action[] TransitionStrategies = new Action[]
    {
        () => { /* One way of performing a transition */ },
        () => { /* Another way of performing a transition */ },
        () => { /* Keep adding methods and calling them here for each transition type */ }
    }

    public static void PerformTransition(int? transitionIndex = null)
    {
        int effectiveIndex;

        // if the transition index is null, use a random one
        if (transitionIndex == null)
        {
            effectiveIndex = new Random().Next(0, TransitionStrategies.Length);
        }
        else
        {
            effectiveIndex = transitionIndex.Value;
        }

        // perform the transition
        TransitionStrategies[effectiveIndex]();

    }
}
static void Main(string[] args)
{
    // create a list to hold the transitions we load
    List<AbstractTransition> transitions = new List<AbstractTransition>();

    // load each module we find in the modules directory
    foreach (string dllFilepath in Directory.EnumerateFiles("Modules", "*.dll"))
        // this should really read from the app config to get the module directory                
    {
        Assembly dllAssembly = Assembly.LoadFrom(dllFilepath);

        transitions.AddRange(dllAssembly.GetTypes()
            .Where(type => typeof(AbstractTransition).IsAssignableFrom(type))
            .Select(type => (AbstractTransition) Activator.CreateInstance(type)));
    }

    // show what's been loaded
    foreach (AbstractTransition transition in transitions)
    {
        Console.WriteLine("Loaded transition with id {0}", transition.TransitionId);

        // execute just to show how it's done
        transition.PerformTransition();
    }

    Console.Read(); // pause
}
Loaded transition with id 2
Performing flip transition
Loaded transition with id 1
Performing slide transition

你可以做很多事情来使它更优雅,但这至少是一个简单的例子,说明了如何使用基于插件的体系结构来提供你所需要的。

你可以尝试使用抽象类,创建一个用于图像转换的基本抽象类

public abstract class ImageTransition
{
    protected int imageId { get; set; }
    public Dictionary<int, Image> ImageDictionary { get; set; }

    protected abstract void TransitionToNextImageId();

    public Image GetNextImage()
    {
        TransitionToNextImageId();
        return ImageDictionary[imageId];
    }
}
公共抽象类ImageTransition
{
受保护的int-imageId{get;set;}
公共字典ImageDictionary{get;set;}
受保护的抽象void transitionNoxtimageId();
公共映像GetNextImage()
{
TransitionOnNextimageId();
返回ImageDictionary[imageId];
}
}
然后创建新的转换类型,这些转换类型继承自该基类,并拥有自己的TransitionOnNextimageId方法实现

public class InTurnImageTransition : ImageTransition
{
    protected override void TransitionToNextImageId()
    {
        if(this.imageId < ImageDictionary.Count)
            this.imageId ++;
    }
}

public class RandomImageTransition : ImageTransition
{
    protected override void TransitionToNextImageId()
    {
        imageId = new Random().Next(0, ImageDictionary.Count);
    }
}
公共类InTurnImageTransition:ImageTransition
{
受保护的重写void transitionOnNextimageId()
{
if(this.imageId