繁体   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