2012-01-28 85 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