C#:如何动态加载/实例化DLL?

时间:2010-09-09 19:17:40

标签: c# dynamic dllimport

我已经看到了一些可能对我有帮助的例子,但是我没有那么多时间来探索它们,因为我今天发现我的老板必须比计划提前一周进行演示,并且我想添加这个新功能。我会尽量保持这种简短和甜蜜。

好的,这就像我第10次尝试纠正这一点,希望它是明确的。这是一个应用程序。需要在DataGridView(已完成)中显示数据行。根据报告(完成),某些行的突出显示不同。大多数报告都有自己的SQL文件,并在运行时从INI文件(完成)实现。但是,有些报告需要调用函数。该应用程序正在使用SQLite数据库。我想拥有作为报告的DLL,所有格式相同,并且所有这些都返回ReportRecord列表。 ReportRecord是在我的主应用程序中定义的类,但我也会在创建它们时在每个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岁)的例子,否则它将无法回答。

5 个答案:

答案 0 :(得分: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");
}

答案 1 :(得分:1)

不要以DLL为原始文件来看待这个,而是使用Assemblies,这就是.NET看待事物的方式。您可以使用Assembly.Load加载程序集。话虽如此,您是否考虑过更通用的解决方案,例如inversion of control

答案 2 :(得分:1)

我真的不明白你到底要做什么,而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);

答案 3 :(得分:0)

考虑使用插件架构(例如Managed Extensibility Framework)来管理报告模块。

答案 4 :(得分:0)

您可能需要考虑使用Managed Extensibility Framework。它使这种类型的操作变得微不足道。

您可以在上面下载.NET 3.5(它已经在.NET 4的框架中了)。通过使用MEF,您只需通过DirectoryCatalog一次性导入所有导出的“报告”的集合,它将为您处理所有接线。

有关详细信息,请参阅Importing Collections here上的帮助。

相关问题