2012-01-28 83 views
1

我创建了一个名为UserSessionModel的类;在这里我存储了一些关于用户的数据,特别是我存储了几个查询和序列化结果的json字符串。在c中使用接口#

我在UserSessionModel几种方法和属性,总体是这样的:

public string SomeUserDataInJson1 { get; set; } 
public string SomeUserDataInJson2 { get; set; } 
.... 3 more properties like this 
public int UserID { get; set; } 

private void GetSomeUserDataInJson1 
{ 
    ObjectData1 TheObjectData1 = new ObjectData1(); 
    UserQueries TheUserQueries = new UserQueries(); 
    JavascriptSerializer TheSerializer = new JavascriptSerializer(); 

    TheObjectData1 = TheUserQueries.GetData1(TheUserID); 

    this.SomeUserData1InJson = TheSerializer.Serialize(TheObjectData1); 
} 

此代码重复5次,作为目标数据,查询的名称和属性SomeUserData这是唯一的变化设置。

有没有办法让这个“更好”的接口或一些其他的C#工具?

谢谢。

+2

为什么选择投票?我确定这是一个非常常见的重构情况。 – frenchie 2012-01-28 13:50:39

+0

@Stegi:我该怎么做? – frenchie 2012-01-28 14:06:15

+0

您应该分离数据,查询和处理(查询执行和序列化)。我建议阅读关于设计模式,控制反转(IoC)和关注点分离的书籍/教程。请参阅http://www.dofactory.com/Patterns/Patterns.aspx – Beachwalker 2012-01-28 14:10:54

回答

2

好吧,让我们假设下列关于你的例子:每个用户(用户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. 

作为你的功课......尝试添加您自己的查询实现和数据进行处理。你如何在这里添加递归? ;-)

+0

好的,谢谢你的回答!我将整合你所描述的概念。感谢您的时间! – frenchie 2012-01-28 16:25:06

+0

请记住,这只是一个示例。在满足实际情况时,样本总是可以改进的在设计组件/体系结构时,可能有所帮助的“指导原则”遵循CQRS原则(命令查询责任分离)http://martinfowler.com/bliki/CQRS.html。 – Beachwalker 2012-01-28 17:11:43

0

首先你一定要使用List<string>string[]。然后你可以增加代码空间和可扩展性。您可以循环并将数据加载到列表中,就像您在那里一样。另一件事,你的意思是TheQueriesTheUserQueries,因为我看不到后者声明或前者使用。

如果你发现自己创造了超过两个类似的属性像你这样做,你应该使用List

其次,接口点是迫使一个目的是实现某些方法等,然后可被调用,在其他类访问。如果这可以帮助你,那么你可以把你的方法放在一个界面中。否则,真的没有意义。

+0

好的,修复了查询语法(错字)。为什么我需要一个字符串列表?你的意思是json字符串的列表,而不是5个不同的属性? – frenchie 2012-01-28 13:47:57

+0

是的,基本上。不要使用名称为“... 1,... 2,... 3”等五个属性。使用'List '而不是 – annonymously 2012-01-28 13:53:38