2009-11-28 154 views
1

您好,非常感謝您的幫助。幫助c#模式

using .Net 3.5 C#;

說我有大約10的方法,所有遵循相同的模式

使用3爲例:

public Customer CreateCustomer(Customer c) { .. } 
public Car CreateCar(Car c) { .. } 
public Planet CreatePlanet(Planet p) { ..} 

每個方法的內部邏輯具有完全相同的模式。

IE:

public Customer CreateCustomer(Customer c) 
{ 
Log.BeginRequest(c, ActionType.Create); 
Validate(customer); 
WebService.Send(Convert(c)); 
Log.EndRequest(c, ActionType.Create); 
} 

public Car CreateCar(Car c) 
{ 
Log.BeginRequest(c, ActionType.Create); 

Validate(c); 

WebService.Send(Convert(c)); 

Log.EndRequest(c, ActionType.Create); 
} 

同樣是與CreatePlanet和其他7分的方法實現。

這些方法是否可以重寫,它們都遵循相同的模式,我覺得我錯過了一些東西......是否還有另一個抽象層次可以派生出來?

問題:應該如何重寫以利用正確的架構模式?

感謝, 史蒂芬

+0

是通用能夠解決你的問題嗎? – Benny 2009-11-28 17:01:33

回答

7

這似乎是一個適合的模板模式的情況下。您可以使所有實體都實現相同的接口/基礎並針對接口執行操作。

我認爲必須知道實際類型的唯一部分是Validate()。它可以通過兩種方式解決:

  1. 讓接口/基本聲明驗證並在每個具體實體中實現它。
  2. 定義具體實體類型和實際驗證策略之間的策略映射。

實施例使用基類抽象驗證 -

實體,在那裏它具有內部的服務,爲創建和基地驗證抽象定義:

public abstract class EntityBase 
{ 
    protected abstract void Validate(); 

    protected void Create(EntityBase c) 
    { 
     Log.BeginRequest(c, ActionType.Create); 
     c.Validate(); 
     WebService.Send(Convert(c)); 
     Log.EndRequest(c, ActionType.Create); 
    } 
} 

混凝土實現者以驗證功能:

public class Customer : EntityBase 
{ 
    private int year; 

    public Customer(int year) 
    { 
     this.year = year; 
    } 

    public void CreateCustomer(Customer c) 
    { 
     Create(c); 
    } 

    protected override void Validate() 
    { 
     if (year < 1900) 
     { 
      throw new Exception("Too old"); 
     } 
    } 
} 

我在原代碼中沒有看到什麼Create返回,所以我將其更改爲無效,以使示例清除

+0

Hello Elisha。感謝這個想法,我現在正在實施它。 問題:您提到:定義具體實體類型與實際驗證策略之間的策略映射。 你的意思是類似於:if(c.GetType()== typeof(Customer))??另外,你知道這是否會降低性能嗎?謝謝Stevne – stevenrosscampbell 2009-11-28 18:03:05

+0

通過映射戰略,這意味着。 你也可以用if(c是Customer)來代替類型比較。我不確定演出會有多糟糕,我想這不會太大,因爲這裏沒有重要的反映。你也會爲每一個沮喪者付出代價,但是這個代價會有點小。虛擬驗證的性能會更好。 – Elisha 2009-11-28 18:33:39

2

我認爲您正在尋找一個generic method解決方案。

public T Create<T>(T t) 
{ 
    Log.BeginRequest(t, ActionType.Create); 
    Validate(t); 
    WebService.Send(Convert(t)); 
    Log.EndRequest(t, ActionType.Create); 
    return t; 
} 
0

您可以使用通用的方法:

T Create<T>(T arg) 

或者只是系統。Object:

object Create(object arg); 
{ 
    Log.BeginRequest(arg, ActionType.Create); 
    Validate(arg); 
    WebService.Send(Convert(arg)); 
    Log.EndRequest(arg, ActionType.Create); 
    return arg; //It must have a return 
} 

Car CreateCar(Car c) 
{ 
    return (Car)Create(c); 
} 
0

如果只有類型不同或者可以創建通用方法,則可以爲這十種類型提取通用接口。

1

是,與一般功能:

public T TrackInstantiation<T>(T entity) 
    { 
    Log.BeginRequest(entity, ActionType.Create); 
    Validate(entity); 
    WebService.Send(Convert(entity)); 
    Log.EndRequest(entity, ActionType.Create); 
    // Don't you also need to return the thing to fulfill the method siugnature ? 
    return entity; 
    } 

我改變了方法的名稱,因爲你不是創建這個方法的對象,(要傳遞一個已經創建的實例),你只是驗證,持續並記錄它的創建。順便說一句,爲什麼不在這裏實際創建對象呢?那麼這將接近稱爲抽象工廠的模式。

你也可以使用界面做同樣的事情。

公共接口ICanBeTracked {/ *沒有方法* /}

修改每個你想傳遞給這個方法,讓他們也umplement此接口的類型,然後只寫你的方法

public ICanBeTracked TrackInstantiation(ICanBeTracked entity) 
    { 
    Log.BeginRequest(entity, ActionType.Create); 
    Validate(entity); 
    WebService.Send(Convert(entity)); 
    Log.EndRequest(entity, ActionType.Create); 
    // Don't you also need to return the thing to fulfill the method siugnature ? 
    return entity; 
    } 

...,併爲每個三種方法通過該方法稱爲上面類型爲ICanBeTracked輸入參數的過載基準

1
public T Create<T>(T c) 
{ 
    Log.BeginRequest(c, ActionType.Create); 
    Validate(customer); 
    WebService.Send(Convert(c)); 
    Log.EndRequest(c, ActionType.Create); 
} 
0

我看到幾個recommen用於模板功能的功能。這很好,但它沒有說明整個故事。我猜這個問題的一部分是你的每個驗證和轉換函數的工作方式都有所不同,這意味着一個簡單的通用函數可能不夠用。

如果是這樣的話,你有幾個選擇。一種是重載驗證/轉換函數,並讓類型系統的重載解析找出要調用的那個。另一個(這是首選)是使用前面推薦的模板模式,並讓每個類型實現一個通用接口。第三種選擇是爲每個方法的函數請求一個委託參數。你已經有了前兩次的例子,所以這裏是怎麼寫的方法,接受委託一個代碼示例:

public T Create<T>(T c, Action<T> validate, Func<T, string> convert) 
{ 
    Log.BeginRequest(c, ActionType.Create); 

    validate(c); 
    WebService.Send(convert(c)); 

    Log.EndRequest(c, ActionType.Create); 
} 
0

你可以使用面向方面的編程應用日誌記錄和驗證。使用PIAB(政策注入應用程序塊)從微軟模式(企業庫的一部分)&實踐團隊(假設配置已經到位),你可以用這樣的事情結束了:

[LogRequest(ActionType.Create)] 
[DoValidate()] 
public T Create<T>(T item) 
{ 
    WebService.Send(convert(item)); 
} 

其中LogRequest是一個定製一個新的ICallHandler的自定義屬性,在該ICallHandler中記錄請求的開始,調用getNext()(將控制權發送給鏈中的下一個ICallHandler,或者如果這是鏈中的最後一個,則將控制權發送給被調用的方法),那麼當控制返回到ICallHandler時,它會記錄請求的結束。

的驗證可能由驗證應用程序塊,其與PIAB 無縫地工作,或者你可以寫自己的驗證處理程序進行處理

AOP可以顯着地減少的代碼,你需要的,只是要小心量不要太過分了。

您可以在企業再圖書館讀到這裏了:http://www.codeplex.com/entlib/