简体   繁体   中英

select values from collection with generic types at runtime

I have a collection of pools

private Dictionary<Type, object> componentPools = new Dictionary<Type, object>();

Each pool can be identified by its type. The object is always Dictionary<Guid, TComponent>() where TComponent as a generic type implements the interface IComponent and the Guid represents a unique ID as the key.

Just for information, a basic addition to these pools would be

public void AddComponentPool<TComponent>() where TComponent : IComponent
{
    componentPools.Add(typeof(TComponent), new Dictionary<Guid, TComponent>());
}

I would like to return an array of Type filled with types which are connected to a Guid . At first I tried to use the long and ugly run

List<Type> componentTypesList = new List<Type>();

foreach (KeyValuePair<Type, object> componentPool in componentPools)
{
    Dictionary<Guid, object> pool = (Dictionary<Guid, object>)componentPool.Value;

    if (pool.Keys.Contains(entityId))
    {
        componentTypesList.Add(componentPool.Key);
    }
}

Type[] componentTypes = componentTypesList.ToArray();

but this code doesn't work anyway.

Dictionary<Guid, object> pool = (Dictionary<Guid, object>)componentPool.Value; crashes because the Value should be TComponent instead of object .

I also tried to use Linq, but this was even worse and doesn't work either.

            Type[] componentTypes = componentPools
                .Select(pool => pool.Key)
                .Where(pool => (Dictionary<Guid, object>)pool.Keys.Contains(entityId))
                .ToArray();

What needs to get fixed?


Update:

To make some things clear, TComponent is a generic and is not available in that method I want to use. My PseudoCode approach would be

    public Type[] GetTypesById(Guid entityId)
    {
        List<Type> componentTypes = new List<Type>();

        foreach (KeyValuePair<Type, object> componentPool in componentPools)
        {
            Dictionary<Guid, object> pool = (Dictionary<Guid, object>)componentPool.Value;

            if (pool.Keys.Contains(entityId))
            {
                componentTypes.Add(componentPool.Key);
            }
        }

        return componentTypes.ToArray();
    }

As @Adam requested, the full code

https://pastebin.com/b400Egzp

The relevant part is the method AddComponentToEntity . Please keep in mind I'm not an experienced programmer :)

Looking at this answer , you could try casting to IDictionary first and work off of that:

public Type[] GetTypesById(Guid entityId)
{
    return componentPools
              .Where(x => ((IDictionary)x.Value)
                  .Contains(entityId))
              .Select(x => x.Key)
              .ToArray();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM