簡體   English   中英

引用未實例化/尚不存在的類

[英]Referencing a class that is not instantiated / does not yet exist

我有一個旨在與外部軟件包集成的Winforms應用程序。 該應用程序從這些程序包中讀取數據,並將其推送到我們的服務器,用戶在此登錄並使用我們的應用程序(App)。

public abstract ClassToImplement
{
    public abstract void DefinedMethod1();
    public abstract void DefinedMethod2();
}

在設計應用程序時,它打算完成95%的集成工作,而剩下的5%(實現類/ App2)則由熟悉第三方軟件的顧問開發。

public class Implemented : ClassToImplement{
    public override void DefinedMethod1(...);
    public override void DefinedMethod2(...);
}

“應用程序”輸出一個類庫,該類庫隨后在實現(App2)中進行引用。 在我們的設計中,我們創建了一個抽象類並定義了方法。 想法是,顧問將下載實現類的回購,並將App作為參考。 然后,他們將為實現,編譯和“瞧!”的方法編寫必要的代碼。

由於明顯的原因,我不想與外部開發人員共享源項目,否則,我將共享完整的解決方案並使用單個應用程序,盡管我知道他們可以通過DLL參考看到很多東西,但這僅僅是讓我們更輕松地控制一切。

App帶來了問題:主要的應用算法需要實例化實現類,然后程序才能完美運行。

在App的Form1.cs中:

ClassToImplement impObj = new Implemented();
impObj.DefinedMethod1();
impObj.DefinedMethod2();

我面臨的挑戰是,如果不實例化類,就無法構建“ App”來輸出DLL。 我尚未實例化代碼,因為我還沒有代碼。

非常高興知道如何依靠(尚未)未編寫的代碼來實現這種抽象,並且,我要做什么的技術術語是什么?

通常這是一個兩步過程:

  1. 找到並加載程序集/ dll:

     Assembly assembly = Assembly.LoadFrom(DLL); 
  2. 實例化實現的類:

     Type type = assembly.GetType(FullNameOfImplemented); AppInstance = (ClassToImplement)Activator.CreateInstance(type, parameters); 

為了使它“工作”,請使用Func,它返回抽象類的實例。

在您的秘密倉庫中:

//Your "App" DLL Project
public abstract class ClassToImplement
{
    public abstract void DefinedMethod1();
    public abstract void DefinedMethod2();
}


public class App : Form
{

    public App(Func<ClassToImplement> initiator)
    {
        InitializeComponent();

        ClassToImplement ci = initiator.Invoke();
        ci.DefinedMethod1();
        ci.DefinedMethod2();
    }
}


//This is in a separate project which will be your startup project internally

public class Dummy : ClassToImplement
{
    public override void DefinedMethod1(){}
    public override void DefinedMethod2(){}
}

public class Program
{
    public static void Main()
    {
        Application.Run(new App(()=> new Dummy()));
    }
}

在與顧問共享的回購中:

// In the repo which is shared with the consultant
// This will be the startup project on the build server, and when the consultant is testing.
public class Implementation : ClassToImplement
{
    public override void DefinedMethod1(){}
    public override void DefinedMethod2(){}
}

public class Program
{
    public static void Main()
    {
        Application.Run(new App(()=> new Implementation()));
    }
}

在構建服務器上,您可以從兩個存儲庫中提取文件,並將啟動項目設置為提供給顧問的項目。 但是,當您在內部進行測試和開發時,可以使用不執行任何操作的實現將啟動項目設置為您的版本。

附帶說明一下,如果您認為正在做的事情需要受到已簽署保密協議的顧問的保護,請確保在發布時將其混淆。

您正在尋找的過程通常稱為存根 在這種情況下,您選擇將集成功能封裝在一個庫中,而不是在Web服務中,但是原理是相同的。

想法是,顧問將下載實現類的回購,並將App作為參考。

這聽起來像您以錯誤的方式獲得了依賴關系。 如果顧問的代碼引用了您的應用程序,則您的應用程序將無法引用它-這將是循環依賴項。 取而代之的是,將您的應用程序分解為以下內容:

App | | App.Integration.Contracts ^ ^ | | | App.Integration.Stub | App.Integration

抽象類(可以很容易地成為C#中的接口)駐留在Contracts程序集中。 這是您的應用程序具有的唯一已編譯依賴項。 然后在運行時使用配置加載存根或使用IoC容器的完整實現。 一個示例是Unity ,您將需要其配置API 引用要在配置文件中使用的真實類型,並更改該類型以更新您的應用程序以使用全部功能。

首先,我想如果您不想與其他開發人員共享代碼,則需要實現適當的插件系統。

其次,您應該針對您的接口而不是針對其實現進行編碼。 首先是因為您沒有它,其次是因為您可能想切換其他第三方軟件的實現。

如果您需要一個實例進行測試或填充,則可以使用手寫的模擬或模擬框架。 如果以后(當其他開發人員交付時)需要一個真實的實例,則可以使用某些設計模式(例如工廠模式)或其他設計模式進行創建。 如果要稍后更改實現,請嘗試避免使用new關鍵字。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM