【问题标题】:Looking for a way to change a variable number of method argument types C#寻找一种方法来更改可变数量的方法参数类型 C#
【发布时间】:2019-03-09 18:13:33
【问题描述】:

Entity Component Systems 中,实体与组件中的数据保持关系,然后每个组件都可以由多个系统操作。每个系统都可以依赖于许多组件。

目前,我在一个基类中实现系统,并完成了查找组件并将其耦合到同一个实体的大部分繁重工作。其中很多都是使用泛型完成的,而且效果很好。

public abstract class System<T1>: System
    where T1: Component
{        

    public override void Update( long delta )
    {
        ComponentStorage<Component> componentStorage1 = GetComponentStorageByType<T1>( );

        List<Entity> entities = GetEntities( );

        if ( componentStorage1 == null )
            return;

        entities.ForEach( e =>
        {
            int index = entities.IndexOf( e );

            if ( componentStorage1[ index ] == null )
                return;

            Update( (T1) componentStorage1[ index ], delta );
        } );
    }

    protected abstract void Update( T1 component1, long delta );
}

继承的类覆盖了名为 Update 的方法,我通过存储中的 update 方法将实例化的组件传递给该方法。

class TestSystem1: System<TestComponent1>
{
    protected override void Update( TestComponent1 component1, long delta )
    {
        Console.WriteLine( $"{component1.Count++}" );
    }
}

这适用于只有一个组件的系统。如果系统有多个组件,我将不得不为许多组件添加另一个通用 Tn,这意味着实现最多无限数量的类。

我研究了可变数量的通用参数,C++11 has it C# does not

我可能可以让反射发挥作用,但在我用尽所有其他选择之前,我宁愿不这样做。

有没有可以满足我需求的设计?我希望它保留继承的类最完整 - 调用一个覆盖、受保护的 Update 方法(或类似方法)并将一个已经转换的组件交给它。

【问题讨论】:

    标签: c#


    【解决方案1】:

    一些可能的选择是:

    • 使用T4 template 生成一组System&lt;&gt; 基类,支持例如1 到 16 个参数。这是一个编译时解决方案。
    • System&lt;T&gt; 只接受一个参数,但如果T 本身不是一个组件,则将其视为一个组合。 IMO,实现和使用都更简单。例如:
        class ComponentsRequired
        {
           Component1 First { get; set; }
           Component2 Second { get; set; }
        }
    
        class TestSystem : System<ComponentsRequired>
        {
            protected override void Update( ComponentsRequired components, long delta )
            {
                Console.WriteLine( $"{components.First}" );
                Console.WriteLine( $"{components.Second}" );
            }
        }
    

    反射可用于获取ComponentsRequired中的属性类型一次并缓存以加速下次使用。

    【讨论】:

    • 我确实喜欢复合的想法,但是你仍然需要在继承的类中以某种方式解压它,这意味着用户实现。 T4 模板看起来对我的问题非常有用,将代码更改并希望能够多次复制代码。
    • @mstehula,你为什么需要解压?复合材料可以按原样传递。在派生类中使用它就像从复合对象中获取属性一样简单。我扩展了代码示例以使其更清晰。 System&lt;T&gt; 基类可以为所有用例实现一次。
    • 我猜解包也是指铸造。无论它是否在复合材料中,我们都不知道您的示例中 First 或 Second 的类型。在我的测试用例中,TestSystem 依赖于知道它使用哪些组件来允许它访问组件数据,这些数据不是从基类 Component 继承的。 @pbalaga
    • @mstehula:仍然不需要强制转换。 ComponentsRequired 是为您希望在派生自 System&lt;T&gt; 的类中操作的每组不同的参数创建的。您知道编写代码时需要使用的确切类型,否则您无法在 TestComponent 类中使用它。不同之处在于,在基类System&lt;T&gt; 中,您必须动态地 获取T 中定义的属性类型,然后为每个此类类型调用GetComponentStorageByType(propertyType)。不应该需要单一的显式强制转换。你现在觉得这更清楚了吗?
    • 是的。在系统旁边创建组合,在我的例子中,它称为 TestSystem1Components。事物继承方面的一切都很好,花花公子,我在弄清楚在基本系统中要做什么时遇到了一些困难。知道更新方法的类型和以前一样,将泛型类型传递给基础系统。由于反射类型查找,不需要强制转换。 @pbalaga
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 2021-12-28
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多