【问题标题】:How to check programatically if an assembly reference exists in c#?如何以编程方式检查 C# 中是否存在程序集引用?
【发布时间】:2013-05-02 16:49:11
【问题描述】:

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

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

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

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

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

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

感谢您的帮助,塞尔玛

【问题讨论】:

    标签: .net c#-4.0 using assembly-references


    【解决方案1】:

    我实际上正在做这样的事情。如果程序集存在/是否可以工作,则会对其进行探测。

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

    • 将这个类的所有功能提取到接口中(我们称之为: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
    • 如果找不到 MyImplementation 程序集(您没有包含它),它将在 MyFacade 中创建 RealExcel 时失败,因此将使用 FakeExcel

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 代码顶部的使用引用怎么样?使用 Excel = Microsoft.Office.Interop.Excel;不会导致电脑上没有office和excel的用户出现程序集引用错误吗?
      • @selmar:程序集只有在使用时才会加载。 using 是不够的。您实际上需要从程序集中枚举或实例化类型。
      【解决方案3】:

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

      【讨论】:

      • 好主意,但是像微软对象库那样分发这样的dll是否合法?
      • 我想是的,它是由微软打造的,页面上没有任何相反的说法。
      猜你喜欢
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-13
      • 1970-01-01
      • 1970-01-01
      • 2012-07-08
      相关资源
      最近更新 更多