从类中更改泛型类型
本文关键字:泛型类型 | 更新日期: 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>();