我有这个类来生成随机对象:
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();
如果我走错路,我还能采取其他任何方式吗?
感谢。
答案 0 :(得分:1)
你不能这样做...
您不需要通用课程
只需使您的方法通用。
基本上只需将所有代码组合在一个方法中
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]);
}
}
现在,如果你担心性能,你可以缓存列表中的类型 字典&LT; string,List&lt;类型&GT;&GT;
答案 1 :(得分:1)
我只使用通用方法,但不是通用类:
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;
}
}
如果你想让这个类保持通用,你或者你必须为每种类型创建一个不同的生成器。
答案 2 :(得分:0)
或者您可以生成生成器:
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>();