从类中更改泛型类型

本文关键字:泛型类型 | 更新日期: 2023-09-27 18:36:55

我有这个类来生成随机对象:

public class Generator<T>
{
    private Random rnd = new Random();
    private List<Type> types = new List<Type>();
    public Generator()
    {
        //can't a generic type constraint that says "implements any interface" so I use this ugly thing...
        if (!typeof(T).IsInterface)
            throw new Exception("Generator needs to be instanciated with an interface generic parameter");
        types = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Contains(typeof(T))).ToList();
    }
    public T GetRandomObject()
    {
        int index = rnd.Next(types.Count);
        return (T)Activator.CreateInstance(types[index]);
    }
    public void SetNewGeneric<N>()
    {
        T = N; //this doesn't work...
        types = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Contains(typeof(T))).ToList();
    }
}

我是这样使用它的:

Generator<IEnemy> generator = new Generator<IEnemy>();
var randomEnemy = generator.GetRandomObject(); //create and return randomly, any object that implements IEnemy...

我的问题是,有没有办法在运行时更改T的类型,以便我可以做类似的事情

generator.SetGeneric<IWeapon>();
var weapon = generator.GetRandomObject();

如果我走错了路,还有其他方法可以做到这一点吗?

谢谢。

从类中更改泛型类型

我只会使用泛型方法,而不是泛型类:

public class Generator
{
    private Random rnd = new Random();
    // Make it so you only have to get the interfaces for a given type once.
    private Dictionary<Type, List<Type>> _typeCache = new Dictionary<Type, List<Type>>();
    public T GetRandomObject<T>()
    {
        List<Type> types = GetTypes<T>();
        int index = rnd.Next(types.Count);
        return (T)Activator.CreateInstance(types[index]);
    }
    private List<Type> GetTypes<T>()
    {
        List<Type> types;
        if (!_typesCache.TryGetValue(typeof(T), out types))
        {
            //can't a generic type constraint that says "implements any interface" so I use this ugly thing...
            if (!typeof(T).IsInterface)
                throw new Exception("Generator needs to be instanciated with an interface generic parameter");
            types = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Contains(typeof(T))).ToList();
            _typesCache[typeof(T)] = types;
        }
        return types;
    }
}
要么

这样,要么如果你想保持类泛型,你必须为每种类型创建一个不同的生成器。

你不能这样做...
您不需要泛型类。
只需使您的方法通用即可。基本上只需将所有代码组合在一个方法中即可

public class Generator
{
    public static T GetRandomObject<T>()
    {
        if(typeof(T).IsInterface)
            throw new Exception("Generator needs to be instanciated with an interface generic parameter");
        Random rnd = new Random();
        var types = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Contains(typeof(T))).ToList();
        int index = rnd.Next(types.Count);
        return (T)Activator.CreateInstance(types[index]);
    }
}

现在,如果您担心性能,您可以缓存列表,如果键入
字典<字符串,列表><类型>>

或者你可以生成生成器:

public class Generator<T>
{
    private readonly Random rnd;
    private List<Type> types = new List<Type>();
    public Generator(Random r)
    {
        rnd = r;
        if (!typeof(T).IsInterface)
            throw new Exception("Generator needs to be instanciated with an interface generic parameter");
        types = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Contains(typeof(T))).ToList();
    }
    public T GetRandomObject()
    {
        int index = rnd.Next(types.Count);
        return (T)Activator.CreateInstance(types[index]);
    }
}
public class MetaGenerator
{
    private readonly Random rnd = new Random();
    public Generator<T> Create<T>()
    {
        return new Generator<T>(rnd);
    }
}
var metaGenerator = new MetaGenerator();
var generator = metaGenerator.Create<IEnemy>();
generator = metaGenerator.Create<IWeapon>();