首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >跨多个静态类调用公共方法?

跨多个静态类调用公共方法?
EN

Stack Overflow用户
提问于 2018-12-12 21:38:50
回答 2查看 705关注 0票数 0

快速笔记

本文中的代码构建在内部构建的DirectX-11引擎之上,这意味着它遵循以下严格模式:

代码语言:javascript
复制
Initialize
while (Running) {
    Update
    Render
}

但是,不要让这影响到您,因为问题与DirectX代码无关,而是与static类和方法有关。

概述

我有一个名为RenderObject的类,它包含一个名为Initialize的方法。此方法负责构建对象的网格、分配纹理、着色器等。

代码语言:javascript
复制
public class RenderObject {
    public virtual void Initialize() { }
}

我还拥有一些static类,这些类包含可重用的资产,如公共纹理、着色器、模型和网格。这样我以后就不用再装子弹了。所有这些static类还包含一个名为Initialize的方法,该方法负责创建这些可重用资产。对于这个问题,我将仅限于Textures类。

代码语言:javascript
复制
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方法。LoadingSystemUpdate方法负责使用Queue加载和初始化对象,这对于提供平滑的视觉反馈非常有用。

代码语言:javascript
复制
 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队列相同的进程。目前我不得不这样做:

代码语言:javascript
复制
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;

我已经将其简化为一个处理消息重复设置的方法,并调用RenderPresent,但这仍然很繁琐,它应该每个对象遍历Update方法一次,以保持与代码其余部分的一致性。

我的思想

我理解static类不能继承class或实现interface,所以我想知道是否有一种方法可以提供static类并以类似的方式调用它的Initialize方法;即使这意味着创建一个单独的方法来完成它。

我现正考虑两个方案:

  • 分别加载静态类。
  • 将静态类转换为实例类,并使用队列调用它们。

第一个选项的问题是,我有12个static类,必须更新进度和反馈消息,引发事件,并为每个类重新呈现场景。

第二个选项的问题是,这些static类只包含static属性,因此定义上应该是static,因为不需要从它们继承或创建它们的实例。

问题

是否有一种方法可以跨多个静态类调用公共方法?

  • 如果方法存在于泛型类型(如objectT ),则可能是调用该方法的一种方法。
  • 也许dynamic类型可以工作(尽管您不能创建static类的实例)?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-12-13 13:21:27

我现正考虑两个方案:

  • 分别加载静态类。
  • 将静态类转换为实例类,并使用队列调用它们。

第三种折衷方法与上面的第二个想法有关,但使用了一种称为Singleton模式的设计模式。和静态类一样,进程中只能有一个类,每个人都得到相同的东西,但是与静态类不同的是,单例类可以实现接口,甚至可以从其他类下降。

对于这个例子,我将使用接口方法。

代码语言:javascript
复制
public interface IInitializable
{
    void Initialize();
}

接口所做的就是强制它的实现者有一个Initialize方法。

我的下一步是创建一个Singleton类。有几个规则可以实现Singleton模式。你的课必须密封。它的构造函数必须是私有的。它必须具有返回单个实例的静态方法或属性。该方法/属性必须是线程安全。

我用懒散来帮我做重活。

代码语言:javascript
复制
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;
}

您对静态类所做的操作有一些细微的差别。如果Foo是一个静态类,您将调用Foo.Initialize();,就像它是Singleton一样,您将调用Foo.Instance.Initialize();

任何其他方法或属性都很可能是非静态的。

把所有的东西组合在一起,你就可以这样写代码了。您的队列不需要知道它包含哪些类。你其实并不在乎。您只想知道它是否有Initialize()方法

代码语言:javascript
复制
   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.
            }
        }
    }

这样,这个类就可以这样使用了。

代码语言:javascript
复制
    YourClass yourClass = new YourClass();
    yourClass.Enqueue(Foo.Instance);
    yourClass.LoadOrUpdate();
票数 1
EN

Stack Overflow用户

发布于 2018-12-12 21:59:49

虽然我希望有一个比这更好和更详细的答案;我已经想出了一个基本的解决方案。我创建了一个单独的Queue<Type>,其中添加了static类。然后使用以下方法调用他们的Initialize方法:

代码语言:javascript
复制
Type t = typesToInit.Dequeue();
t.GetMethod("Initialize").Invoke(null, new object[] { 0 });

这很好,而且相当干净,但我不禁想知道是否有更好的方法来做到这一点?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53751764

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档