基于字符串创建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包含默认构造函数和密钥、日期、时间、数字等属性。

基于字符串创建AND实例化对象的工厂

是否合理取决于您的需求。

你可以这样分析字符串:

// 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构造函数"是什么意思。没有抽象构造函数这回事。如果你指的是抽象基类的构造函数,那么当子类被实例化时,它不可避免地会被调用。