1

我正在尝试为非常具体的财务计算编写一个小型 c#/.net 库。

我编写了几个仅依赖于 .net 框架的标准程序集的类。也就是说,具有这些类的库只需要 .net 框架(4.0 客户端)。

现在我需要一个额外的类来进行 excel 集成。此类将需要与 microsoft office 和 excel 相关的附加程序集引用,例如它们各自的对象库。

我的问题是:这个图书馆的一些用户可能有office和excel,有些没有。

如何将此附加类添加到库中,以便两种类型的用户都可以使用该库而不会出错?

更准确地说:如果用户没有office和excel,则用户必须能够运行除excel相关的所有类而不会出错。

感谢您的帮助,塞尔玛

4

3 回答 3

3

我实际上正在做这样的事情。如果它们存在/将工作,则对程序集进行了探测。

当然,您可以通过多种方式做到这一点,但这就是我的结尾:

  • 将此类的所有功能提取到接口中(我们称之为:IExcel)并为其添加 IsAvailable 属性
  • 实现了实现 IExcel 的假类,并从 IsAvailable 返回“false”(当然,从其他方法抛出 NotSupportedException)。
  • 使用 IExcel 的实际实现创建新程序集(重要:新程序集)
  • 使用“Create”实现 Factory 类,它将决定应该返回哪一个并在解析(或测试)时捕获异常

组装:MyFacade

// the interface
public interface IExcel
{
    bool IsAvailable { get; }
    // your stuff
}

// the fake implementation
public class FakeExcel: IExcel
{
    public IsAvailable { get { return false; } }
    // your stuff should probalby throw NotSupportedException
}

组装:MyImplementation

// real implementation
public class RealExcel: IExcel
{
    private bool? _isAvailable;

    public bool IsAvailable
    {
        // return value if it is already known, or perform quick test
        get { return (_isAvailable = _isAvailable ?? PerformQuickTest()); }
    }

    private bool PerformQuickTest()
    {
        try
        {
            // ... do someting what requires Excel
            // it will just crash when it cannot be found/doesn't work
        }
        catch // (Exception e)
        {
            return false;
        }
        return true;
    }
}

组装:MyFacadeFactory

public class ExcelFactory
{
    public static IExcel Create()
    {
        // delay resolving assembly by hiding creation in another method
        return Try(NewRealExcel) ?? new FakeExcel();
    }

    private static IExcel Try(Func<IExcel> generator)
    {
        try
        {
            var result = generator();
            if (result.IsAvailable) 
                return result;
        }
        catch // (Exception e)
        {
            // not interested
        }
        return null; // didn't work exception or IsAvailable returned 'false'
    }

    // this could be implemented as delegate but it's 
    // safer when we put NoInlining on it
    [MethodImpl(MethodImplOptions.NoInlining)]
    private static IExcel NewRealExcel()
    {
        return new RealExcel();
    }
}

会发生什么?

  • 如果你有 Excel 并且可以找到 MyImplementation 程序集,它将被加载,RealExcel 类将被创建然后使用
  • 如果您没有 Excel 但确实有 MyImplementation 程序集,它将被加载,将创建 RealExcel 类,但在“PerformQuickTest”上将失败,因此将使用 FakeExcel
  • 如果在 MyFacade 中创建 RealExcel 时找不到 MyImplementation 程序集(您没有包含它),它将失败,因此将使用 FakeExcel

您当然可以通过动态加载和反射(更少的代码行)来完成所有这些事情,但使用起来有点笨拙。我发现这种方法反射最少。

于 2013-05-08T16:49:34.500 回答
2

这应该开箱即用。程序集按需加载,即在需要时加载。只要没有 Excel 的用户没有使用 Excel 相关的类,就应该没有错误。

于 2013-05-02T17:04:07.160 回答
0

你试过ILMerge吗?这将使您能够将所需的 dll 添加到您的可执行文件中,这样您就可以确保用户拥有所需的程序集

于 2013-05-03T14:47:22.667 回答