[英]C# - Factory pattern using reflection or how?
I'm developing a game in console c#, that you can read maps created in files.我正在控制台 c# 中开发一款游戏,您可以读取在文件中创建的地图。 For doing so, i'm reading a file and storing that into a string.
为此,我正在读取一个文件并将其存储到一个字符串中。 Then i'm reading each character individually and depending on the character, I need to create an object using the factory pattern.
然后我单独读取每个字符并根据字符,我需要使用工厂模式创建一个 object。 I don't know how to do it without coupling the code.
如果不耦合代码,我不知道该怎么做。
I have the main entity Object. From object inherit different objects, like: Box, Wall, Grass, Tree.我有主要实体 Object。从 object 继承不同的对象,如:盒子、墙、草、树。 Each one is represented by a character in the file and translated to another character in the game, (B)ox = '■', (W)all = '▓', (G)rass = 'v', (T)ree = '↑'.
每一个都由文件中的一个字符表示并翻译成游戏中的另一个字符,(B)ox = '■', (W)all = '↓', (G)rass = 'v', (T)ree ='↑'。 The way I done that is by placing a property char "Model" in the Object with getter only, and in each object I override the getter with the corresponding model.
我这样做的方法是在 Object 中放置一个属性字符“模型”,仅使用吸气剂,在每个 object 中,我用相应的 model 覆盖吸气剂。
Now, while I'm reading the file map mentioned before I need to tell the factory which object to build depending on the character read.现在,当我读取之前提到的文件 map 时,我需要根据读取的字符告诉工厂要构建哪个 object。 I dont want to make a big switch(character) because it will be coupled, because for each object I want to add I will have to add a new case in the switch.
我不想做一个大开关(字符),因为它会耦合,因为对于每个我想添加的 object,我都必须在开关中添加一个新的案例。 Is any better way of doing so?
有更好的方法吗?
Example of class Box: class 框示例:
public class Box : Object
{
public override char Model { get { return '■'; } }
public Box()
{
this.Name = "box";
this.MapCharacter = 'B';
this.Colors = new List<ConsoleColor>() { ConsoleColor.DarkYellow };
this.Destructible = true;
this.Passable = false;
this.SeeThrough = false;
this.Health = 200;
}
public override void OnDestroy()
{
}
}
Example code of Factory:工厂示例代码:
public class ObjectFactory : IObjectFactory
{
public Object GetObject(char mapCharacter)
{
switch (mapCharacter)
{
case 'B':
return new Box();
case 'T':
return new Tree();
case 'W':
return new Wall();
case 'G':
return new Grass();
default:
return null;
}
}
}
My idea was using Reflection get the Model of each class inherted from Object and somehow return that class, but that seems poor code我的想法是使用反射获取从 Object 继承的每个 class 的 Model 并以某种方式返回 class,但这似乎是糟糕的代码
There are pros and cons of going with reflection (personally I would not go this way in general case) but with current code you can improve it a bit and reduce the boilerplate by "converting" switch
to dictionary:使用反射有利有弊(在一般情况下我个人不会 go 这种方式)但是使用当前代码你可以稍微改进它并通过“转换”
switch
到字典来减少样板:
public class ObjectFactory
{
private static readonly Dictionary<char, Func<MyObject>> _objectFactory = new Dictionary<char, Func<MyObject>>()
{
{ 'B', () => new Box() },
// ...
};
public Object GetObject(char mapCharacter)
{
if(_objectFactory.TryGetValue(mapCharacter, out var factory))
{
return factory();
}
return null;
}
}
If you will decide that adding items to dictionary every time is to much - I would recommend to look into source generators , if this approach is to much - do not forget to "cache" the reflection.如果您决定每次都向字典添加项目太多了——我建议查看源代码生成器,如果这种方法太多了——不要忘记“缓存”反射。
It is worth to take a look Activator.CreateInstance method.值得一看Activator.CreateInstance方法。
If a map has full name of class, then it is possible to create an instance like this:如果 map 的全名是 class,则可以创建这样的实例:
public class InstanceHelper
{
public static object Get(string fullyQualifiedName)
{
Type t = Type.GetType(fullyQualifiedName);
return Activator.CreateInstance(t);
}
}
So the above code can be called like this:所以上面的代码可以这样调用:
Box box = InstanceHelper.Get("Box") as Box;
You can use this code sample .您可以使用此代码示例。 There is a class by name of
EnhancedShapeFactory
and it uses reflection.有一个名为
EnhancedShapeFactory
的 class,它使用反射。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.