动态加载装配

时间:2012-09-27 04:20:30

标签: c# excel

我需要动态加载程序集。目前我正在使用“Microsoft.Office.Microsoft.Office.Interop.dll”。我需要打开一个excel文件并从中获取工作表和数据。谁能告诉我怎么办呢?

Assembly SampleAssembly = Assembly
          .Load("Microsoft.Office.Interop.Excel, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");

if (SampleAssembly != null)
{
    Type type = SampleAssembly.GetType("Microsoft.Office.Interop.Excel.ApplicationClass");
    Object AppClass = Activator.CreateInstance(type);

   //How will I get ApplicationClass object and Workbooks objects here?
}

4 个答案:

答案 0 :(得分:3)

利用dynamic

 Type type = SampleAssembly.GetTypes().Single(t => t.Name == "ApplicationClass");
 dynamic appClass = Activator.CreateInstance(type);

 var workbook = appClass.Workbooks.Open("C:\\test.csv");
 var worksheet = workbook.Worksheets[1];

答案 1 :(得分:2)

如果您不能/不想使用动态,我会定义一个带有接口(或一组接口)的项目,公开您需要使用的excel方法/对象,并且您可以在代码中引用任何参考实际的excel dll。然后在引用excel的不同项目中实现它,并将动态加载。

这样的事情:

public interface IExcelApp
{
    IExcelWorkbook OpenWbk(string aPath);
    // other stuff
}

public interface IExcelWorkbook
{
    //the stuff you need
}

实现(在我称之为ExcelBridge的项目中):

public class ExcelApp : IExcelApp
{
    private ApplicationClass _app;

    public ExcelApp()
    {
    }

    public IExcelWorkbook OpenWbk(string aPath)
    {
        return new ExcelWorkbook(_app.Workbooks.Open(aPath));
    }
}

public class ExcelWorkbook : IExcelWorkbook
{
    private Workbook _wbk;

    public ExcelWorkbook(Workbook aWbk)
    {
        _wbk = aWbk;
    }
}

然后您的代码可能是这样的:

Assembly SampleAssembly = Assembly.Load("ExcelBridge", Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c");

if (SampleAssembly != null)
{
    Assembly YourExcelAssembly = Assembly.Load("ExcelBridge.dll");
    Type type = YourExcelAssembly .GetType("ExcelApp");
    IExcel AppClass = Activator.CreateInstance(type) as IExcelApp;

   //now you can write:
   IExcelWorkBook aWbk = AppClass.Open("your xls path");
}

答案 2 :(得分:0)

以下是您在C#中的表现方式

using Microsoft.Office.Interop.Excel;
Type type = SampleAssembly.GetType("Microsoft.Office.Interop.Excel.ApplicationClass");
var application = Activator.CreateInstance(type);
var workbook = application.Workbooks.Open(fileName);
var worksheet = workbook.Worksheets[1] as Microsoft.Office.Interop.Excel.Worksheet;

答案 3 :(得分:0)

如果您使用的是.NET 3.5,则无法使用dynamic关键字。您唯一的选择是使用一系列代理类(手动编写或自动生成),如@Francesco所述。但是,如果您需要访问许多Excel类/函数/属性,那么手动方法非常麻烦。您必须为您需要的每个成员编写一个函数/属性代理。

管理它的关键是,不是编写大量代理函数,而是将处理Excel的所有代码放在一个单独的软件层(如数据访问层,DAL)中,放在不同的库项目中。该层只为应用程序提供了一些高级接口(只有少数成员函数),因此应用程序甚至不知道MS Excel自动化的使用情况。

请注意,即使您不想动态加载程序集,这种Excel访问代码的封装也是一种很好的做法。例如,如果您发现令人沮丧的话,您可能更容易使用其他技术替换Office自动化,例如ADO.NET和reading from / writing to Excel files Microsoft.ACE.OLEDB.12.0提供程序,您也会在x64平台中感到沮丧!


例如,如果要从Excel文件中获取工作表和数据,可以在名为Utils.OfficeAutomation的项目中提供以下接口(不提及Microsoft.Office.Interop.Excel.dll):

interface IExcelLayer {
    ...
    bool ImportFrom(string fileName, string sheetName, out object[,] cells, bool skipHeaderRow = true);

    // a few other members...
    ...
}

然后在一个名为Utils.OfficeAutomation.Impl的单独项目中实现它,该项目引用Utils.OfficeAutomation和真实Microsoft.Office.Interop.Excel.dll

class ExcelMagician : IExcelLayer {
    ...
    bool ImportFrom(string fileName, string sheetName, out object[,] cells, bool skipHeaderRow = true)
    {
         Excel.Application excelApp = new Excel.Application()
         ...
    }
    ...
}

主应用程序仅引用Utils.OfficeAutomation。作为回报,Utils.OfficeAutomation以某种方式负责动态查找和加载Utils.OfficeAutomation.Impl,或者在出现问题时生成错误:

IExcelLayer m_instance = null;

...

try
{
    Assembly assembly = Assembly.Load("Utils.OfficeAutomation.Impl");
    Type excelType = assembly.GetType("Utils.OfficeAutomation.Impl.ExcelMagician");
    m_instance = (IExcelLayer) Activator.CreateInstance(excelType);

}
catch (Exception e)
{
    throw new Exception("Couldn't load Excel assembly.")
}

如果未安装适当版本的Microsoft Excel,则加载程序集Utils.OfficeAutomation.Impl会失败,或者调用ImportFrom之类的成员会产生异常。

您最终需要在Utils.OfficeAutomation内编写包装类作为Excel访问层或Excel功能的网关。