C# Randomize inherited class 没有硬编码
C# Randomize inherited class without hardcoding
我想要实现的是通过派生名称 class 或枚举名称生成一个随机派生 class。虽然我的代码在这种情况下有效,但如果我决定扩展它,它将需要大量的硬编码,对我来说这似乎是一个糟糕的解决方案。
这是我的示例代码:(UnitTypes 变量包含所有派生的 class 动态名称,所以我觉得它可能有用 - 但我可以弄清楚如何使用。)
public void Run()
{
var UnitTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.BaseType == typeof(Unit));
Unit NewMonster = new Unit(); //<---
konny: //for testing things out.
int RandomType = new Random().Next(0, UnitTypes.Count());
switch (RandomType)
{
case 0:
NewMonster = new Dingo();
break;
case 1:
NewMonster = new Buffalo();
break;
case 2:
NewMonster = new Dog();
break;
}
Console.WriteLine($"A wild {NewMonster.Name} appears");
NewMonster.Attack();
Console.ReadLine();
goto konny;
}
为了示例,Baseclass + 1 派生。
public class Unit
{
public Enemies Name { get; set; }
public enum Enemies
{
Dingo, Buffalo, Dog
}
public virtual void Attack()
{
//nothing to see here
}
}
class Dingo : Unit
{
public Dingo()
{
Name = Enemies.Dingo;
}
public override void Attack()
{
Console.WriteLine($"{Name} gnaws at your brain");
}
}
这样的事情怎么样。首先创建一个基地class(我不知道你为什么把它命名为Unit
,我把我的命名为BaseAnimal):
namespace AnimalsTest
{
public abstract class BaseAnimal
{
public enum EnemiesTypes
{
Dingo, Buffalo, Dog
}
public abstract IEnumerable<EnemiesTypes> Enemies { get; }
public abstract void Attack();
}
}
请注意,它是一个 abstract
(不可实例化)并且任何子 classes 都需要实现一个 Enemies
属性 getter 和Attack
方法。
然后我创建了三个子classes(在同一个命名空间):
class Dingo : BaseAnimal
{
public override IEnumerable<EnemiesTypes> Enemies =>
new List<EnemiesTypes> { EnemiesTypes.Buffalo, EnemiesTypes.Dog };
public override void Attack()
{
Console.WriteLine($"{nameof(Dingo)} Gnaws at your brain");
}
}
class Buffalo : BaseAnimal
{
public override IEnumerable<EnemiesTypes> Enemies =>
new List<EnemiesTypes> { EnemiesTypes.Dog };
public override void Attack()
{
Console.WriteLine($"{nameof(Buffalo)} Runs you down");
}
}
class Dog : BaseAnimal
{
public override IEnumerable<EnemiesTypes> Enemies =>
new List<EnemiesTypes> { EnemiesTypes.Buffalo };
public override void Attack()
{
Console.WriteLine($"{nameof(Dog)} Barks at you");
}
}
这些都非常简单class,你可以把它们变得更复杂。
最后一个测试例程,可以锻炼我认为你想要的东西。我从 enum
的值中获取 classes 的名称并随意实例化它们。
private static readonly Random Random = new Random();
public static void Test()
{
var animalClasses = Enum.GetNames(typeof(EnemiesTypes)).Select(n => n.ToString()).ToArray();
var thisAssembly = Assembly.GetExecutingAssembly().FullName;
for (var i = 0; i < 6; ++i)
{
var className = nameof(AnimalsTest) + "." + animalClasses[Random.Next(0, animalClasses.Length)];
var animal = (BaseAnimal) Activator.CreateInstance(thisAssembly, className).Unwrap();
animal.Attack();
Console.WriteLine($"{animal.GetType().Name} has enemies: {string.Join(", ",animal.Enemies.Select(e=>e.ToString()))}");
Console.WriteLine();
;
}
}
请注意,测试代码不知道它正在使用的 classes 的名称,它全部从枚举的值中提取。
每次我运行这个,我得到不同的结果(因为,嗯,Random
)。但是,这是典型的 运行:
的输出
Buffalo Runs you down
Buffalo has enemies: Dog
Dog Barks at you
Dog has enemies: Buffalo
Buffalo Runs you down
Buffalo has enemies: Dog
Dog Barks at you
Dog has enemies: Buffalo
Dingo Gnaws at your brain
Dingo has enemies: Buffalo, Dog
Dingo Gnaws at your brain
Dingo has enemies: Buffalo, Dog
我想要实现的是通过派生名称 class 或枚举名称生成一个随机派生 class。虽然我的代码在这种情况下有效,但如果我决定扩展它,它将需要大量的硬编码,对我来说这似乎是一个糟糕的解决方案。
这是我的示例代码:(UnitTypes 变量包含所有派生的 class 动态名称,所以我觉得它可能有用 - 但我可以弄清楚如何使用。)
public void Run()
{
var UnitTypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => t.BaseType == typeof(Unit));
Unit NewMonster = new Unit(); //<---
konny: //for testing things out.
int RandomType = new Random().Next(0, UnitTypes.Count());
switch (RandomType)
{
case 0:
NewMonster = new Dingo();
break;
case 1:
NewMonster = new Buffalo();
break;
case 2:
NewMonster = new Dog();
break;
}
Console.WriteLine($"A wild {NewMonster.Name} appears");
NewMonster.Attack();
Console.ReadLine();
goto konny;
}
为了示例,Baseclass + 1 派生。
public class Unit
{
public Enemies Name { get; set; }
public enum Enemies
{
Dingo, Buffalo, Dog
}
public virtual void Attack()
{
//nothing to see here
}
}
class Dingo : Unit
{
public Dingo()
{
Name = Enemies.Dingo;
}
public override void Attack()
{
Console.WriteLine($"{Name} gnaws at your brain");
}
}
这样的事情怎么样。首先创建一个基地class(我不知道你为什么把它命名为Unit
,我把我的命名为BaseAnimal):
namespace AnimalsTest
{
public abstract class BaseAnimal
{
public enum EnemiesTypes
{
Dingo, Buffalo, Dog
}
public abstract IEnumerable<EnemiesTypes> Enemies { get; }
public abstract void Attack();
}
}
请注意,它是一个 abstract
(不可实例化)并且任何子 classes 都需要实现一个 Enemies
属性 getter 和Attack
方法。
然后我创建了三个子classes(在同一个命名空间):
class Dingo : BaseAnimal
{
public override IEnumerable<EnemiesTypes> Enemies =>
new List<EnemiesTypes> { EnemiesTypes.Buffalo, EnemiesTypes.Dog };
public override void Attack()
{
Console.WriteLine($"{nameof(Dingo)} Gnaws at your brain");
}
}
class Buffalo : BaseAnimal
{
public override IEnumerable<EnemiesTypes> Enemies =>
new List<EnemiesTypes> { EnemiesTypes.Dog };
public override void Attack()
{
Console.WriteLine($"{nameof(Buffalo)} Runs you down");
}
}
class Dog : BaseAnimal
{
public override IEnumerable<EnemiesTypes> Enemies =>
new List<EnemiesTypes> { EnemiesTypes.Buffalo };
public override void Attack()
{
Console.WriteLine($"{nameof(Dog)} Barks at you");
}
}
这些都非常简单class,你可以把它们变得更复杂。
最后一个测试例程,可以锻炼我认为你想要的东西。我从 enum
的值中获取 classes 的名称并随意实例化它们。
private static readonly Random Random = new Random();
public static void Test()
{
var animalClasses = Enum.GetNames(typeof(EnemiesTypes)).Select(n => n.ToString()).ToArray();
var thisAssembly = Assembly.GetExecutingAssembly().FullName;
for (var i = 0; i < 6; ++i)
{
var className = nameof(AnimalsTest) + "." + animalClasses[Random.Next(0, animalClasses.Length)];
var animal = (BaseAnimal) Activator.CreateInstance(thisAssembly, className).Unwrap();
animal.Attack();
Console.WriteLine($"{animal.GetType().Name} has enemies: {string.Join(", ",animal.Enemies.Select(e=>e.ToString()))}");
Console.WriteLine();
;
}
}
请注意,测试代码不知道它正在使用的 classes 的名称,它全部从枚举的值中提取。
每次我运行这个,我得到不同的结果(因为,嗯,Random
)。但是,这是典型的 运行:
Buffalo Runs you down
Buffalo has enemies: Dog
Dog Barks at you
Dog has enemies: Buffalo
Buffalo Runs you down
Buffalo has enemies: Dog
Dog Barks at you
Dog has enemies: Buffalo
Dingo Gnaws at your brain
Dingo has enemies: Buffalo, Dog
Dingo Gnaws at your brain
Dingo has enemies: Buffalo, Dog