1

我有一个从队列中读取字符串消息并“处理它们”的请求。每条消息都有一个 4 位数的“标识符/密钥”开头,然后是日期、时间和另一个数字……从那时起,每条消息都是不同的,需要不同的处理。

我的想法是使用工厂来创建所需类型的对象,并同时调用 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包含默认构造函数和键、日期、时间、数字等属性。

4

4 回答 4

1

是的,您可以而且是一种正确且明智的方法。如果你可以有一个默认的构造函数,事情会发生一些变化,如果构造函数与另一个具体实现不同,也会发生变化。最简单的方法是使用无参数构造函数。有了这个先决条件,你可以有这样的东西:

Type t = Type.GetType(string.Format("Handlers.MyHandlers.Message{0}",messageType));
var handler = Activator.CreateInstance(t) as IMessageThing;

为了将字符串传递给消息,您可以在IMessageThing接口中定义一个函数,让我们Init在创建消息后立即调用它,或者更好的是,在AbstractMessage类中使用一个构造函数,然后调用它像这样的激活器:

var handler = Activator.CreateInstance(t,body) as IMessageThing;

AbstractMessage调用抽象函数的构造函数Init(string body)中,每个具体的消息都需要实现自己的解析器。

添加更多错误处理,您就完成了。

于 2013-02-13T11:21:01.750 回答
1

是否有意义取决于您的要求。

您可以像这样分析字符串:

// 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
}

当然你仍然需要做一些错误处理,但我希望我能给你一个好的起点。

我使用字典的原因是性能。Activator.CreateInstance 不是很快,使用 Type.GetType 查找也很慢。除了在 Dictionary 中使用类型作为值之外,您还可以使用以下内容:

Dictionary<string, Action<IMessageThing>> _factories;
_factories = new Dictionary<string, Action<IMessageThing>>();
_factories.Add("Message1000", () => new Message1000());

并创建您的对象,您可以调用:

var instance = _factories["Message1000"]();
于 2013-02-13T11:28:36.670 回答
0

一种方法是拆分字符串,,但将最大计数设置为 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

于 2013-02-13T11:21:09.300 回答
0

您可以将每条消息传递给处理程序,处理程序将检查它是否可以处理这种类型的消息。如果是这样,它将解析并返回一些对象,否则它将返回例如 null 并且您将知道询问不同的处理程序。

或者您构建一个解析器,该解析器了解遵循通用格式的初始部分,然后使用查找表查找特定的消息处理程序,该处理程序将解析剩余的消息并实例化正确的类型。(将公共部分传递给它的构造函数)。

我不明白“创建所需类型的对象并调用 asbtract 构造函数”是什么意思。没有抽象构造函数之类的东西。如果您的意思是抽象基类的构造函数,则在实例化子类时不可避免地会调用它。

于 2013-02-13T11:21:31.430 回答