基于字符串创建AND实例化对象的工厂
本文关键字:对象 工厂 实例化 AND 字符串 创建 | 更新日期: 2023-09-27 17:58:59
我有一个从队列中读取字符串消息并"处理它们"的请求。每条消息都有一个4位数的"标识符/密钥"a开头,后面跟着日期、时间和另一个数字。。。从那时起,每条消息都是不同的,需要不同的处理。
我的想法是使用工厂创建一个所需类型的对象,同时调用asbtract构造函数。
这样做明智吗
如果是…如何?
例如
1000,2013-02-13,09:00:00,492,....................
4000,2013-02-13,09:00:01,492,....................
1000,2013-02-13,09:00:02,74664,....................
4003,2013-02-13,09:00:03,1010,....................
4000,2013-02-13,09:00:04,493,....................
构建类对象
Message1000 : AbstractMessage, IMessageThing
Message4000 : AbstractMessage, IMessageThing
Message4003 : AbstractMessage, IMessageThing
其中AbstractMessage
包含默认构造函数和密钥、日期、时间、数字等属性。
是否合理取决于您的需求。
你可以这样分析字符串:
// inside your actual factoryMethod...
var lines = ...;
foreach(var line in lines)
{
var tokens = line.Split(',');
// for split: you can also specify the max. amount of items if the ..... part can
// consist of more the dots.
CreateMessageObject(tokens); // eventually add to list of AbstractMessage or whatever
}
static FactoryClassConstructor()
{
_typeMap = new Dictionary<string, Type>();
_typeMap.Add("Message1000", typeof(Message1000));
// todo: add other message types
// you also could write a method which will use the class name of the
// type returned by typeof(XYZ) to assure the correct value as key
}
private Dictionary<string, Type> _typeMap;
private AbstractMessage CreateMessageObject(string[] tokens)
{
// simple error checking
if(tokens.Count != 5)
// todo: error handling
return null;
var type = typeMap[tokens[0]];
var instance = Activator.CreateInstance(type);
instance.Date = DateTime.Parse(tokens[1]);
instance.Time = DateTime.Parse(tokens[2]);
// todo initialize other properties
}
当然,你仍然需要做一些错误处理,但我希望我能给你一个好的起点。
我之所以会使用字典是因为性能。激活器。CreateInstance不是很快,并且使用Type进行查找。GetType也很慢。不使用字典中的Value类型,您也可以使用以下内容:
Dictionary<string, Action<IMessageThing>> _factories;
_factories = new Dictionary<string, Action<IMessageThing>>();
_factories.Add("Message1000", () => new Message1000());
并创建您可以调用的对象:
var instance = _factories["Message1000"]();
是的,您可以而且是一种正确而明智的方法。如果您可以有一个默认的构造函数或没有默认的构造函数,情况会发生一些变化,如果构造函数在不同的具体实现中不同,情况也会发生变化。最简单的方法是使用无参数构造函数。有了这个先决条件,你就可以拥有这样的东西:
Type t = Type.GetType(string.Format("Handlers.MyHandlers.Message{0}",messageType));
var handler = Activator.CreateInstance(t) as IMessageThing;
为了将字符串传递给消息,您可以在IMessageThing
接口中定义一个函数,让它在消息创建后立即调用Init
,或者更好的做法是,在AbstractMessage
类中使用一个字符串的costructor,并在activator中调用它,如下所示:
var handler = Activator.CreateInstance(t,body) as IMessageThing;
在AbstractMessage
的构造函数中,调用抽象函数Init(string body)
,因此每个具体消息都需要实现自己的解析器。
添加更多的错误处理,您就完成了。
一种方法是在,
上拆分字符串,但将最大计数设置为5,这应该将数字后面的所有值分组为一个值:
var parts = your_string.split(new char[] {','},5);
然后您只需要使用Activator.CreateInstance()
来创建您的消息实例。例如:
Type type = Type.GetType(String.Format("Message{0}",parts[0]));
var instance = Activator.CreateInstance(type) as IMessageThing;
然后,您可以从parts
中填写其余属性。
您可以将每条消息传递给处理程序,处理程序将检查它是否可以处理这种类型的消息。如果是这样,它将解析并返回一些对象,否则它将返回例如null,并且您将知道询问不同的处理程序。
或者,您可以构建一个解析器,该解析器了解遵循通用格式的初始部分,然后使用查找表查找特定的消息处理程序,该处理程序将解析剩余的消息并实例化正确的类型。(将公共部分传递给其构造函数)。
我不明白你说的"创建一个所需类型的对象并同时调用asbtract构造函数"是什么意思。没有抽象构造函数这回事。如果你指的是抽象基类的构造函数,那么当子类被实例化时,它不可避免地会被调用。