2012-10-11 60 views
2

我有一些與MVP模式有關的問題,特別是在哪裏創建我的所有類的實例。目前這些都是在program.cs文件中創建的。雖然這很有效,但我知道這是糟糕的設計。我很感激,如果有人可以給我一些指示,這應該如何結構。MVP,類應該在哪裏創建?

internal static class Program 
{ 
    /// <summary> 
    /// The main entry point for the application. 
    /// </summary> 
    [STAThread] 
    private static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 

     var browser = new BrowserWindow(); 
     var helper = new MainPresenterHelper(); 
     var userInterface = new MainForm(); 
     var entity = new UserInputEntity(); 

     var readerWriter = new ReaderWriter(); 
     var manager = new IOManager(readerWriter); 
     var verif = new VerificationManager(manager); 
     var entityVerification = new EntityVerification(verif); 

     var logger = new Logger(entity, readerWriter, true); 
     var verifyRow = new VerifyRow(entity, logger); 
     var verification = new VerificationOfDataTypes(entity, logger, verifyRow, new Status(), readerWriter); 

     var verify = new CsvFileVerification(entityVerification, verification, logger); 

     var cts = new CancellationTokenSource(); 
     var source = new CancellationTokenSourceWrapper(cts); 

     var presenter = new MainPresenter(userInterface, browser, helper, entity, verify, source); 

     Application.Run(userInterface); 
    } 
} 
+0

你試圖使用MVP的WinForms? –

+0

是的,我知道它不理想,但據說它應該是可行的。 –

回答

6

如果你想知道「爲什麼這篇文章這麼久!?」這是因爲我正在與C#聊天室中的Hans和其他人聊天,並且有一個想法(我想)他想學什麼


漢斯,

這是完全可行中的WinForms使用的MVP,我們把它盛放的一箇舊的Windows CE 6設備(WinForm的風格)的應用上,甚至還包括一個完整的CQRS週期。無論如何。

我即將列出的東西不是必需您的程序,但我認爲這對您作爲開發人員非常有用。你需要學習的東西(在我看來)是對象生命週期和依賴層次結構。這些東西可能有正確的名稱,但希望這是足夠描述。

因此,當您的應用程序啓動時,您實際正在做的是實例化所有內容。雖然你的程序可能會使用所有這些東西,但它是否真的需要將它們全部在這樣的地方實例化?如果沒有其他的東西,它會讓這個班負責太多。當你運行你的應用程序時,你想要做的第一件事就是顯示一個我假設的UI。所以,理想情況下,這就是第一種方法應該存在的一切。

我看到你正在將實例化的各種對象傳遞到下一個對象中,這是一個好的開始 - 這意味着你基本上已經逐行輸出了依賴關係樹。但是,在能夠繼續執行此操作之前,您需要重新考慮依賴關係。基本上,你的目標是什麼這個類需要才能運行。不要再深思熟慮了(即如果這個類需要X,我必須得到Y,因爲X需要這個)。你只想爲你的每個類找到第一層依賴關係。

我的建議是放入一個Dependency Container並使用Constructor Injection,與現在不同。通常,通過抽象對象的動作和屬性,從實際實現中開始這個過程。

public interface IDoStuff 
{ 
    string AProperty { get; set; } 

    bool SomeMethod(int anArgument); 
} 

public class TheImplementation : IDoStuff 
{ 
    public string AProperty { get; set; } 

    public bool SomeMethod(int anArgument) 
    { 
     return false; 
    } 

    public void AnotherMethod() 
    { 
     this.AProperty = string.Empty 
    } 
} 

所以,乍一看,你可能想知道什麼是點到了這一切,當然這只是讓你的程序不必要的複雜。那麼,重點是從消費者中抽象出實現細節。

而不是着眼的:

public class MyConsumer 
{ 
    private readonly TheImplementation myDependency; 

    public MyConsumer(TheImplementation myDependency) 
    { 
     this.myDependency = myDependency 
    } 

    public void ExposedMethod() 
    { 
     this.myDependency.SomeMethod(14) 
    } 
} 

我們的目標是消費者只引用接口:

public class MyConsumer 
{ 
    private readonly IDoStuff myDependency; 

    public MyConsumer(IDoStuff myDependency) 
    { 
     this.myDependency = myDependency 
    } 

    public void ExposedMethod() 
    { 
     this.myDependency.SomeMethod(14) 
    } 
} 

這是什麼給你的靈活性!這意味着您可以對實施進行更改,甚至可以徹底更換實施,而無需與消費者聯繫。因爲您可以將這些接口的實現換成假版本(稱爲mocks),這樣您就可以絕對隔離地測試應用程序的組件(消費者) - 更快速地測試應用程序的組件(消費者)測試,更好的測試。沒有更多的測試演示者導致數據庫查詢或意味着您必須啓動IIS Express才能運行您的WCF服務,以便某些類可能需要。

之後,依賴注入變得非常簡單。您的應用程序啓動變爲composition root,並處理您的真實實現與接口的綁定。

一旦綁定完成,我曾經使用過的所有依賴容器(Ninject是我個人的最愛,緊隨其後的是Unity)能夠自動檢測到依賴關係樹,並通過簡單地請求根節點實例化整個對象圖。太多的談話,太少的代碼=)下面是一個例子:

[STAThread] 
private static void Main() 
{ 
    // assuming ninject 
    IKernel kernel = new StandardKernel(); 

    // some people hate self binds, but you may find this easier than 
    // creating interfaces for all your existing classes 
    kernel.Bind<BrowserWindow>().ToSelf(); 
    kernel.Bind<MainPresenterHelper>().ToSelf(); 
    kernel.Bind<MainForm>().ToSelf(); 
    kernel.Bind<UserInputEntity>().ToSelf(); 

    // this is where we use the splitting implementation from interface 
    kernel.Bind<IReaderWriter>().To<ReaderWriter>(); 
    kernel.Bind<IIOManager>().To<IOManager>(); 
    kernel.Bind<IVerificationManager>().To<VerificationManager>(); 
    // .... etc 

    //If you do them all correctly, you can simply have the following line 

    Application.Run(kernel.Get<MainForm>()); 
} 

我希望這有助於幫助你?如果沒有,那麼該死的,花了很長時間寫這個了...... =)

相關問題