[英]Choosing a Subclass without knowing the name of it in C#
編輯1:如果有人對此有更好的標題,請隨時告訴我或自己編輯。
編輯2:感謝您的貢獻,給出的答案幾乎是我需要的一些調整,我很感謝這里的小內容。 今天真的學到了很多!
這里的小東西我現在要敲一下頭了。
我想創建一個幻燈片,並希望Image對象本身具有邏輯。
該程序應該能夠設置所需的過渡,或者只是一個隨機的過渡,因此
我想用普通的東西創建一個過渡超類並進行特殊化
它在子類中。 所以我有Transitions.cs(當前沒有任何代碼)
並且沒有派生類。 我希望它以添加單個.cs文件的方式
擴展Transitions.cs,並且不更改其他任何代碼即可實現新的Transition。
我目前擁有的代碼看起來像這樣,但我想我
描述比代碼更有用
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++;
}
}
我確實研究了狀態設計模式,但是我不想實現它,因為我只需要選擇一次狀態並使其短暫。 圖像對象本身的壽命只有大約幾秒鍾。 我不想執行通常的if嵌套,或者只是將所有代碼放入SlideImages.cs中。 是否有任何良好的指導或對繼承以及此類內容非常深入的內容?
欣賞所有輸入。
對於您想做的事情有兩種簡單的解決方案。 您的基本問題是,您希望能夠向程序中動態添加功能,但又不想知道要使用哪些功能。 實現此目的的最簡單方法是使用Actions
而不是子類化。 當您想添加另一個過渡時,只需更新一個動作列表,如下所示:
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]();
}
}
上面的方法很簡單,但是所有邏輯(或至少根據對過渡實現實際工作的位置對邏輯的引用)都放在一個位置。 根據您要添加的過渡數量以及有多少開發人員正在使用此代碼庫,它也有可能變得非常混亂。 它還要求有權訪問完整代碼庫的人員添加所有功能,並且每次添加新轉換時都需要重新編譯。
從長遠來看,更復雜但更可維護和更靈活的方法是使用模塊(或出於我們的目的使用插件)。 該方法中的每個轉換都由共享模塊或特定模塊提供,並且是基本AbstractTransition
類的子類,或者是ITransition
接口的實現,具體取決於您要執行的操作。 使用生成后任務將所有模塊dll放置在主程序可訪問的單個目錄中(獲得許可的其他任何人也可以在其中放置過渡模塊dll)。 程序啟動時,它將動態加載該目錄中的所有dll(只要在該目錄中添加了正確的dll,就無需重新編譯即可),並提取實現該接口的所有類。 這些接口實現中的每一個都被實例化並放入數據結構中,之后您可以使用與上述PerformTransition
方法類似的策略來基於ID而不是索引執行一個或多個隨機操作。 如果您願意,我可以使用該結構的示例來編輯此問題。
編輯:您尚未要求它,但是這是一個帶有插件/模塊的示例。
首先,創建一個項目以加載和運行轉換。 本示例將使用一個名為ModuleDemo
的項目。 給它一個主要的方法是這樣的:
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
}
您會注意到該方法引用了AbstractTransition
類。 現在,我們為此創建一個單獨的TransitionModule
項目。 這是模塊將引用的項目:
namespace TransitionModule
{
public abstract class AbstractTransition
{
public readonly int TransitionId;
public abstract void PerformTransition();
protected AbstractTransition(int transitionId)
{
TransitionId = transitionId;
}
// you can add functionality here as you see fit
}
}
現在,我們有了要實現的插件的抽象過渡類和功能正常的插件加載器,我們可以繼續創建一些過渡插件。
我在解決方案中為此創建了一個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");
}
}
}
SlideTransition
項目中的第二個模塊:
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
目錄中加載Modules
,因此請轉到主項目的/bin/Debug
目錄並創建一個Modules
目錄。 也將過渡插件項目的/bin/Debug
目錄中的所有dll復制到該目錄中。 所有這些都可以在以后通過生成后任務自動執行。
繼續運行程序。 您應該獲得如下輸出:
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];
}
}
然后,創建新的Transition類型,這些類型從該基類繼承並具有自己的TransitionToNextImageId方法的實現;
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);
}
}
這使您可以根據需要構建一些自定義過渡。
-編輯-您當然會在調用GetNextImage方法之前填充字典ImageDictionary。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.