我可以通过公共API防止泄露第三方库的“详细信息”吗?

时间:2015-03-24 15:22:39

标签: c# .net api-design

我正在创建一个库,它是第三方库的包装和扩展。有没有办法防止无意中暴露第三方库?或者至少得到关于它的警告?我不希望我的库的用户引用(依赖于)第三方库。

例如,可以这样做:

public class MyLibraryClass
{
    public void Use3rdParty(3rdPartyClass c)
    {
        // Do something...
    }
}

我知道将方法标记为内部将解决问题。令我恼火的是,我犯了错误并暴露了一些应该是内部的方法。我想在将来避免这种情况。

此外,我想问一下从第三方类公开隐式转换是否安全:

public class MyLibraryClass
{
    public static implicit operator MyLibraryClass(3rdPartyClass c)
    {
        // Conversion...
    }
}

必须将运算符定义为static和public,因此此方法不能是内部的。根据我的想法,它应该是安全的,因为在我的库之外,用户不应该看到这种转换方法,因此甚至可以尝试这种转换。

总的来说,我并不担心安全性,所以我不介意用反射用户可以访问“任何东西”。它更多的是关于API的清洁,而不是混淆用户。

我正在使用VS 2010和.NET 4.0。

编辑:总结并澄清一下,我的问题是您可能无意中(偶然)暴露了一些第三方库详细信息,并且您没有得到编译器或任何其他任何警告。我正在寻找一些方法来告诉编译器只能在具有内部访问权限或访问权限较低的地方使用程序集。

3 个答案:

答案 0 :(得分:3)

让我们从观察开始:

  

我不希望我的图书馆用户参考(依赖)第三方图书馆。 ...

public void Use3rdParty(3rdPartyClass c)

您只是强迫您的API用户依赖第三方库。 (如果没有准备好传入第三方库对象,他们就无法调用您的API。)

话虽如此,什么是一个好的解决方案取决于您自己的库主要扩展第三方库,或者它是否主要使用该第三方库作为私有实现细节

您的图书馆主要扩展第三方图书馆:

我不会进一步深入研究,因为我不确定你的问题在这种情况下是否有意义:如果你的图书馆扩展了第三方图书馆,那么它的用户应该使用第三方 - 派对图书馆已经存在,因此您不需要首先隐藏它。

您的库主要使用第三方库作为私有实现细节:

然后你应该完全隐藏你自己的API背后的第三方库。这意味着第三方库的类型可能根本不会出现在您自己的API方法签名中。

一个好的方法(带来一些小的开销)是在你自己的包装类中包装所有第三方库的类型(或者至少是那些你将要暴露的类型):

namespace ThirdPartyLibrary
{
    public class ThirdPartyLibrary.Quux
    {
        public void Foo() { … }
        …
    }
}

namespace YourLibrary
{
    public sealed class Quux  // has same methods as the third-party library's type
    {
        private readonly ThirdPartyLibrary.Quux wrapped;
        …
        public Foo() { wrapped.Foo(); }  // forward calls to the underlying type
    }
}

然后根据这些包装类(也是API的一部分,btw)编写libary公共API的其余部分:

namespace YourLibrary
{
    public class Frobbler
    {
        public void Frobble(Quux c)
        {                // ^^^^
            …            // your wrapper class, not the third-party original 
        }
    }
}

(此外,将第三方DLL合并到您自己的(by including it as an embedded resource and handling the AppDomain.AssemblyResolve event或使用ILMerge等工具)可能是一个好主意,这样只有在没有DLL的情况下才能部署您的库它可能取决于。)

答案 1 :(得分:2)

我认为如果你有隐式转换运算符,Visual Studio会询问任何使用你的库的人,他们引用了那些运算符中引用的任何类型。如果您有任何类型在第三方库中实现接口,则相同。

你可以使用Roslyn来做这类事情,但听起来你正在使用旧版本的Visual Studio,所以这可能不是一个选择。

另一种选择是使用反射来构建第三方库中的类型列表,然后使用反射来扫描库中公共类型的公共/受保护成员,以查看它们中是否有任何类型使用这些类型。将其添加为"单位"测试或在构建过程中自动运行的东西。

您可以使用以下内容获取程序集中的类型列表:

Type[] types = typeof(SomeTypeInAnAssembly).Assembly.GetTypes()

使用第三方程序集中的类型列表,然后您可以遍历程序集中的类型并检查每个构造函数(type.GetConstructors),每个属性(type.GetProperties),每个字段({ {1}})。这些方法采用type.GetFields值,您需要指定public和non-public,instance和static来获取所有方法。然后,您需要筛选BindingFlags结构上公共(IsPublic属性)或受保护(IsFamily属性)的内容。检查方法/构造函数的参数类型以及返回类型。

答案 2 :(得分:0)

我会考虑使用ViewModel或DTO(数据传输对象)来隐藏第三方库的实现/细节。这将提供您完全控制的界面,该界面与第三方API的任何实现分开。

这样,如果您切换到另一个库,则不必重写API以匹配您正在进行的工作的任何新的/切换/抛出的自身依赖项,并将其从API使用者中抽象出来只要您不在新的ViewModel或DTO中公开这些详细信息。