簡體   English   中英

C#:如何動態加載/實例化DLL?

[英]C#: How do I dynamically load/instantiate a DLL?

我已經看到了一些可能對我有幫助的示例,但是我沒有太多的時間去探索它們,因為我今天發現我的老板們必須比原計划提前一周進行演示,我想添加此新功能。 我會盡量保持簡短和甜美。

好的,這就像我第十次嘗試糾正此問題以使其更清晰,希望是的。 這是一個應用程序。 數據行需要在DataGridView中顯示(完成)。 根據報告(完成),某些行以不同的方式突出顯示。 大多數報告都有自己的SQL文件,並在運行時從INI文件實現(完成)。 但是,某些報告需要調用功能。 該應用程序正在使用SQLite數據庫。 我想擁有作為報告的DLL,它們都具有相同的格式,並且它們都返回ReportRecord的列表。 ReportRecord是在我的主應用程序中定義的類,但是在創建每個DLL時,我也會在每個DLL中定義它。 我想實例化DLL,將其稱為“ GetRecords”函數,然后在我的主應用程序中使用它。 這是一些偽代碼。 如果你們可以告訴我是否可行,或者給我一個更好的方法的想法,我將不勝感激。

偽碼

 foreach (string str in System.IO.Directory.GetFiles("C:\\ReportDlls", "*.dll"))
 {
   //Instantiate DLL e.g. newReport
   //_lstReportRecords.AddRange(newReport.GetReportRecords());
 }    

反正有這樣做嗎?

目前,在找到答案之前,我需要補充以下內容:

        private void RefreshReports(string strReportTitle)
        {
            _lstReportRecords = _lstReportRecords.Where(rr => rr.Description != strReportTitle).ToList<ReportRecord>();
            string strColumn = iniFile.GetString(strReportTitle, "Column", "");


            if (strColumn != null)
            {
                _lstReportRecords.AddRange(_dataController.BuildReportList(strColumn, strReportTitle, GetReportSQL(strReportTitle)));
            }
            else
            {
                switch (strReportTitle)
                {
                    case "Improper Indenture":
                        _lstReportRecords.AddRange(_dataController.ImproperIndenture());
                        break;
                    case "Skipping Figure":
                        _lstReportRecords.AddRange(_dataController.SkippingFigure());
                        break;
                    default: break;
                }
            }
            FormatCells();
        }

感謝大家。

編輯 :對不起,老兄,看着這些東西真讓我感到愚蠢。 就像,我的腦子一片空白,全神貫注。 :)你們提供的可能是最好的方法,但是由於我必須在星期二之前准備好質量的演示,並且在那之前不應再添加任何需要功能的報告,因此我將保持這種狀態。 我的老板出門演示后,我將繼續實施。 但是現在,除非我看到一個非常非常(針對2歲兒童)的例子,否則它將無法解決。

您可以簡單地創建一個實現以下接口的C#庫項目,然后將二進制文件存儲在數據庫或文件系統中。 然后,您可以從原始程序集字節/文件路徑加載程序集,以實例化對象。 通過反射,您還可以直接調用構造函數,但是我更喜歡將工廠模式用於此類任務。

public interface IReportModule
{
}

public interface IReportModuleFactory
{
    IReportModule Create();
}

private static IReportModule CreateReportModuleFromRawAssemby(byte[] rawAssembly)
{
    var reportModule = Assembly.Load(rawAssembly);
    var factoryType = reportModule.GetExportedTypes()
        .FirstOrDefault(x => x.IsAssignableFrom(typeof(IReportModuleFactory)));
    if (factoryType != null)
    {
        var reportModuleFactory = (IReportModuleFactory)
            reportModule.CreateInstance(factoryType.FullName);
        return reportModuleFactory.Create();
    }
    else
        throw new NotImplementedException("rawAssembly does not implement IReportModuleFactory");
}

不要以DLL(原始文件)的角度來看問題,而要用Assemblies(.NET看到事物的樣子)的觀點來看。 您可以使用Assembly.Load加載程序Assembly.Load 話雖如此,您是否考慮過更通用的解決方案,例如控制反轉

我不太了解您到底想做什么,IOC可能是您的選擇。 但是據我了解,您可以通過純粹的反思做到這一點。

提醒您,這遠非理想的方法,但您正在要求它:)

它就到了(我的頭頂,所以如果有任何問題請不要向我開槍,它應該很近,盡管不是萬無一失的)

// load assembly
var assemblyWithReport = Assembly.LoadFrom("Path of your assembly"); 

// or another Loadxx to get the assembly you'd 
// like, whether it's referenced or not

// load type
var reportType = assemblyWithReport.GetTypes().ToList()
   .Where(t => t.Name == "ReportRecord").Single();

// create instance of type
var instance = Activator.CreateInstanceOf(reportType);

// get getrecords method of the type
var getRecordsMethod = reportType.GetMethod("GetRecords");

// invoke getrecords method on the instance
object result = getRecordsMethod.Invoke(instance, null);

考慮一個用於管理報表模塊的插件體系結構,例如Managed Extensibility Framework

您可能要考慮使用托管擴展框架 它使這種類型的操作變得微不足道。

您可以在上方下載.NET 3.5的版本(它已經在.NET 4的框架中)。 通過使用MEF,您可以通過DirectoryCatalog一次導入所有導出的“報告”的集合,它將為您處理所有連接。

有關詳細信息,請參閱此處的有關導入集合的幫助。

暫無
暫無

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

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