好吧,让我们假设下列关于你的例子:每个用户(用户ID)定义不同的查询处理你遇到数据。
我们的数据容器类...这里很简单,只包含一个字符串。
public class Data
{
public string Content { get; set; }
}
下一步,让我们看看在查询......可能是使用该接口(可以使用事件,该响应,但让保持简单在这里)。
public interface IQuery
{
Data Process(Data data);
}
你可以通过增加用户id到IQUERY接口有关系的用户,但我宁愿有另一个接口来解决:
public interface IUserQueryProvider
{
IEnumerable<IQuery> GetQuerysForUser(uint id);
}
这样你就可以改变你的用户查询在单独的地方解决。
你也会有一个序列化器/转换器。好的,让我们在这里创建一个接口来处理(处理)数据的序列化。
public interface ISerializer
{
string Serialize(Data data);
}
现在,让我们来看看实现,首先是串行的......没有做什么神奇这里,你应该在你需要的对象的序列化的东西填补(JSON,... )
public class JavascriptSerializer : ISerializer
{
public string Serialize(Data data)
{
return data.Content; //whatever you want do instead for serialization
}
}
现在让我们转到我们的查询。我假设你对设计模式不是很熟悉,而你的意思就像是命令模式(用于处理作业,请参阅我的注释中的链接以获取有关设计模式的更多信息)。3个实现如下样本:
public class ReplaceQuery : IQuery
{
private readonly string match;
private readonly string text;
public ReplaceQuery(string match, string text)
{
this.match = match;
this.text = text;
}
public Data Process(Data data)
{
return data.Content.Contains(match) ? new Data {Content = data.Content.Replace(match, text)} : null;
}
}
public class GreetingToQuery : IQuery
{
private readonly string greeting;
private readonly string place;
public GreetingToQuery(string greeting, string place)
{
this.greeting = greeting;
this.place = place;
}
public Data Process(Data data)
{
return data.Content.Contains(greeting) ? new Data {Content = data.Content + place + "."} : null;
}
}
public class LineEndingQuery : IQuery
{
public Data Process(Data data)
{
return data.Content.LastIndexOf(".", StringComparison.Ordinal) == data.Content.Length - 1 &&
data.Content.Length > 0
? new Data {Content = "\n"}
: null;
}
}
如果我们想要解析哪些查询属于用户,我们需要我们的IUserQueryProvider实现。在这种情况下,它只不过是一本字典(但可以轻松切换到其他实现)。
public class SampleQueryProvider : Dictionary<uint, IEnumerable<IQuery>>, IUserQueryProvider
{
public IEnumerable<IQuery> GetQuerysForUser(uint id)
{
IEnumerable<IQuery> queries;
TryGetValue(id, out queries);
return queries;
}
}
最后但并非最不重要的......一切的胶水。我在这里为我们的“发电机引擎”添加了另一个接口。
public interface IScriptGenerator
{
event Action<string> Script;
void Generate(Data data, IEnumerable<IQuery> queries);
}
为了使它更灵活的我做了接口/实现以下由拉尔夫·韦斯特法尔推出了一款设计原理称为基于事件的组件(EBC)。如果你对这个话题感兴趣,Google是你的朋友。
public class SampleScriptGenerator : IScriptGenerator
{
private readonly ISerializer serializer;
public event Action<string> Script;
public SampleScriptGenerator(ISerializer serializer)
{
this.serializer = serializer;
}
public void Generate(Data data, IEnumerable<IQuery> queries)
{
foreach (string serialized in from query in queries select query.Process(data) into result where result != null select serializer.Serialize(result))
{
OnSerialize(serialized);
}
}
private void OnSerialize(string serialized)
{
var handler = Script;
if (handler != null) handler(serialized);
}
}
现在可以把它放在一起,让我们飞:
static void Main()
{
var generator = new SampleScriptGenerator(new JavascriptSerializer());
generator.Script += Console.Write; // bind to console output here
var queryProvider = new SampleQueryProvider
{
{
1, // user with id 1
new List<IQuery>
{
new ReplaceQuery("<name>", "frenchie"),
new GreetingToQuery("bonjour", "the universe"),
new LineEndingQuery()
}
},
{
2, // user with id 2
new List<IQuery>
{
new ReplaceQuery("<name>", "stegi"),
new GreetingToQuery("hello", "the world"),
new LineEndingQuery()
}
}
};
var data1 = new Data {Content = "My name is <name>."};
var data2 = new Data {Content = "I say hello to "};
var data3 = new Data {Content = "I say bonjour to "};
var data4 = new Data {Content = "."};
// you cold combine data and user query execution into lists and loops, too
generator.Generate(data1, queryProvider.GetQuerysForUser(1));
generator.Generate(data2, queryProvider.GetQuerysForUser(1));
generator.Generate(data3, queryProvider.GetQuerysForUser(1));
generator.Generate(data4, queryProvider.GetQuerysForUser(1));
generator.Generate(data1, queryProvider.GetQuerysForUser(2));
generator.Generate(data2, queryProvider.GetQuerysForUser(2));
generator.Generate(data3, queryProvider.GetQuerysForUser(2));
generator.Generate(data4, queryProvider.GetQuerysForUser(2));
Console.ReadKey();
}
}
你应该看到:
My name is frenchie.
I say bonjour to the universe.
My name is stegi.
I say hello to the world.
作为你的功课......尝试添加您自己的查询实现和数据进行处理。你如何在这里添加递归? ;-)
为什么选择投票?我确定这是一个非常常见的重构情况。 – frenchie 2012-01-28 13:50:39
@Stegi:我该怎么做? – frenchie 2012-01-28 14:06:15
您应该分离数据,查询和处理(查询执行和序列化)。我建议阅读关于设计模式,控制反转(IoC)和关注点分离的书籍/教程。请参阅http://www.dofactory.com/Patterns/Patterns.aspx – Beachwalker 2012-01-28 14:10:54