本文中的代码建立在内部DirectX-11
引擎之上,这意味着它遵循以下严格的模式:
Initialize
while (Running) {
Update
Render
}
但是,不要让这吓倒您,因为问题与DirectX
代码无关,而与static
类和方法无关。
我有一个名为RenderObject
的类,其中包含一个名为Initialize
的方法。此方法负责构建对象的网格,分配纹理,着色器等。
public class RenderObject {
public virtual void Initialize() { }
}
我还有一些static
类,它们包含可重复使用的资源,例如常见的纹理,着色器,模型和网格。这样,我不必稍后重新加载它们。所有这些static
类还包含一个名为Initialize
的方法,该方法负责创建这些可重用资产。对于这个问题,我将只限于Textures
类。
public static class Textures {
public static Texture2D Dirt { get; private set; }
public static Texture2D Grass { get; private set; }
public static void Initialize() {
Dirt = new Texture2D(...);
Grass = new Texture2D(...);
}
}
最后,我有一个名为LoadingSystem
的类,该类负责加载可重用资产和初始化对象。我在引擎的Initialize
方法内部初始化该类,然后分别在引擎的Update
方法中调用该类的Update
方法。 LoadingSystem
的{{1}}方法负责使用Update
加载和初始化对象,这对提供平滑的视觉反馈很有用。
Queue
我想用与 public class LoadingSystem {
public bool Loading { get; private set; } = true;
private Queue<RenderObject> objectsToRender;
public void AddForLoad(RenderObject obj) => objectsToRender.Enqueue(obj);
public void Update() {
if (objectsToRender.Count > 0) {
RenderObject obj = objectsToLoad.Dequeue();
obj.Initialize();
} else Loading = false;
}
}
队列相同的过程在这些Initialize
类上调用方法static
。目前,我不得不这样做:
RenderObject
我将其简化为处理消息的重复设置并调用CurrentMessage = "Loading Textures";
Render();
Present();
Textures.Initialize();
Progress = ++objectsLoaded / objectsToLoad;
CurrentMessage = "Loading Shaders";
Render();
Present();
Shaders.Initialize();
Progress = ++objectsLoaded / objectsToLoad;
CurrentMessage = "Loading Models";
Render();
Present();
Models.Initialize();
Progress = ++objectsLoaded / objectsToLoad;
和Render
的方法,但这仍然很繁琐,应该通过{{1} }方法每个对象一次,以与其余代码保持一致。
我了解到Present
类不能从Update
继承或实现static
,所以我想知道是否有一种方法可以提供class
类并进行调用其interface
方法以类似的方式;即使这意味着创建一个单独的方法来完成它。
我目前考虑了两种选择:
第一个选项的问题是我有12个static
类,并且必须更新进度和反馈消息,引发事件并为每个场景重新渲染场景。
第二个选项的问题在于,这些Initialize
类仅包含static
个属性,因此根据定义,它们应该为static
,因为无需继承它们或创建一个他们的实例。
是否可以在多个静态类之间调用通用方法?
static
或static
之类的通用类型,该方法是否可以调用该方法?object
类型可以工作(尽管您不能创建T
类的实例)?答案 0 :(得分:1)
我目前考虑了两种选择:
- 分别加载静态类。
- 将静态类转换为实例类,并与队列一起调用。
第三种折衷方法与上述第二个想法有关,但是使用一种称为“单例模式”的设计模式。像静态类一样,您的过程中只能有一个,每个人都会得到相同的东西,但是与静态类不同,Singletons可以实现接口,甚至可以继承其他类。
在此示例中,我将使用接口方法。
def function(salary):
year_salary = salary * 12
return year_salary
接口的所有作用是强制其实现者具有Initialize方法。
我的下一步是创建Singleton类。有几个规则可以实现Singleton模式。您的课程必须被密封。它的构造函数必须是私有的。它必须具有静态方法或属性才能返回单个实例。该方法/属性必须是线程安全的。
我曾经用Lazy为我做繁重的事情
public interface IInitializable
{
void Initialize();
}
与静态类所做的操作有一些细微的差异。如果Foo是静态类,则您将调用public sealed class Foo : IInitializable
{
public void Initialize()
{
// Initialize my foo
}
private Foo()
{
}
private static Lazy<Foo> fooLazy = new Lazy<Foo>(() => new Foo());
public static Foo Instance => fooLazy.Value;
}
,因为它是Singleton,因此您将调用Foo.Initialize();
任何其他方法或属性很可能都是非静态的。
将它们全部拉在一起,您可以编写这样的代码。您的队列不需要知道其拥有的类。你其实不在乎。您只想知道它具有Initialize()方法
Foo.Instance.Initialize();
然后可以像这样使用此类
public class YourClass
{
private Queue<IInitializable> objectsToLoad = new Queue<IInitializable>();
public void Enqueue(IInitializable obj)
{
this.objectsToLoad.Enqueue(obj);
}
public void LoadOrUpdate()
{
// Update Method
if (objectsToLoad.Count > 0)
{
IInitializable obj = objectsToLoad.Dequeue();
obj.Initialize();
}
else
{
// Loading complete.
}
}
}
答案 1 :(得分:0)
尽管我希望有比这更好,更详细的答案;我已经提出了一个基本的解决方案。我创建了一个单独的Queue<Type>
,在其中添加了static
类。然后,使用以下代码调用其Initialize
方法:
Type t = typesToInit.Dequeue();
t.GetMethod("Initialize").Invoke(null, new object[] { 0 });
这很好用,很干净,但是我不禁怀疑是否有更好的方法?