0

我正在寻找您对一段代码的反馈/建议。

基本上,我有一个这样的 SOA:

struct Entities {
    pub meshes: FakeArena<Mesh>,
    pub lights: FakeArena<Light>,
}

我可以通过他的“句柄”访问一个特定的值(每个句柄都绑定到特定的类型),所以我可以通过entities.meshes.get(&handle).

到目前为止,一切都很好,但我试图通过相应的竞技场动态检索值来实现这一点。通过做entities.get(&handle)如果句柄类型是Mesh,我返回entities.meshes.get(&handle)。我的Entities结构有一个名为的方法get

fn get<T: Any>(&self, handle: &Handle<T>) -> &T {
    let mut entity: Option<&dyn Any> = None;
    let any = handle as &dyn Any;

    any.downcast_ref::<Handle<Mesh>>()
        .map(|handle| entity = Some(self.meshes.get(handle) as &dyn Any));

    any.downcast_ref::<Handle<Light>>()
        .map(|handle| entity = Some(self.lights.get(handle) as &dyn Any));

    if entity.is_none() {
        panic!("Type not found in stored entites.");
    }

    entity
        .unwrap()
        .downcast_ref::<T>()
        .expect("Error while downcasting the entity type")
}

操场

这完美地工作。我将泛型类型转换为具体类型,然后再转换为泛型类型,但这似乎很奇怪和棘手。

也许我遗漏了一些东西,或者您对此有更好的想法;你会怎么做?:)

4

1 回答 1

2

您在这里不需要任何动态调度,普通的静态调度就足够了。

创建一个特征,该特征给出对您的容器结构的引用。每个组件类型都实现了这个特征并选择容器的适当字段。然后,在您的get方法中要求该特征并使用它:

struct Mesh;
struct Light;

struct Entities {
    meshes: Vec<Mesh>,
    lights: Vec<Light>,
}

trait Example {
    fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self;
}

impl Example for Mesh {
    fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self {
        &entities.meshes[0]
    }
}

impl Example for Light {
    fn get_in<'a>(&self, entities: &'a Entities) -> &'a Self {
        &entities.lights[0]
    }
}

impl Entities {
    fn get<T: Example>(&self, handle: T) -> &T {
        handle.get_in(self)
    }
}

fn example(entities: &Entities) {
    let m = entities.get(Mesh);
    let l = entities.get(Light);
}
于 2019-11-12T00:37:24.310 回答