API 的 C# 重构 Facade
C# refactoring Facade for API
我为我的应用程序创建了一个 dll
。我正在使用 Facade design pattern
封装 API,因为他们的决定让一些程序员(不是我的组织)感到不舒服。
他们的 API 是这样工作的:
- 初始化 DiadocApi 对象
- 获取令牌的授权
为了初始化 DiadocApi 对象,我需要 developerKey
(获取订阅)。
对于授权我需要 login
, password
.
我的决定很糟糕,因为它是一个单例,我需要进行单元测试。我可以更改我的代码吗?
//I GET IT FROM NUGET PACKAGE
using Diadoc.Api;
public sealed partial class DiadocApiFacade
{
private static readonly object _mutex = new object();
private static DiadocApiFacade _instance;
private string _token;
private DiadocApi _api;
private DiadocApiFacade() { }
public static string DefaultUrl => "url was here";
public string DefaultFromBoxId { get; set; }
public DiadocApi Api { get => _api; private set => _api = value; }
public static DiadocApiFacade GetInstance()
{
if (_instance == null)
{
lock (_mutex)
{
if (_instance == null)
{
_instance = new DiadocApiFacade();
}
}
}
return _instance;
}
public string Authenticate(string login, string password, string privateDeveloperKey)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(developerKey))
throw new ArgumentNullException();
Api = new DiadocApi(developerKey, DefaultUrl, new WinApiCrypt());
return _token = _api.Authenticate(login, password);
}
//method for example, >60% methods like that
public Document GetDocument(string messageId, string documentId, string boxId = null)
{
return _api.GetDocument(_token, boxId ?? DefaultFromBoxId, messageId, documentId);
}
}
我假设您想对消耗 DiadocApiFacade
.
的 您的 代码进行单元测试
依赖倒置来拯救!用接口抽象你的DiadocApiFacade
。使用 工厂模式 来创建对象。下面是一个简单的示例,但如果您需要外观以某种方式运行(例如设置 class 以更改它连接到的位置),您可以扩展工厂。
GetOrCreate
将 return 相同的实例,但如果您在项目中使用依赖项 injection framework(有许多可能满足您的需求),请改用它。
public interface IDiadocApiFacade
{
string Authenticate(string login, string password, string privateDeveloperKey);
public Document GetDocument(string messageId, string documentId, string boxId);
public Document GetDocument(string messageId, string documentId);
}
public class DiadocApiFacadeFactory
{
private static IDiadocApiFacade? _instance = null;
public IDiadocApiFacade Create() //Add parameters
{
return new DiadocApiFacade();
}
public IDiadocApiFacade GetOrCreate()
{
if(_instance == null)
_instance = Create();
return _instance;
}
}
public sealed partial class DiadocApiFacade : IDiadocApiFacade
{
internal DiadocApiFacade() { }
public string Authenticate(string login, string password, string privateDeveloperKey) => string.Empty;
public Document GetDocument(string messageId, string documentId)
=> GetDocument(messageId, documentId, null);
public Document GetDocument(string messageId, string documentId, string? boxId) => new Document();
}
然后你可以使用 [moq)[https://www.nuget.org/packages/moq/] 进行单元测试并伪造 IDiadocApiFacade
[=16 的实现=]
我为我的应用程序创建了一个 dll
。我正在使用 Facade design pattern
封装 API,因为他们的决定让一些程序员(不是我的组织)感到不舒服。
他们的 API 是这样工作的:
- 初始化 DiadocApi 对象
- 获取令牌的授权
为了初始化 DiadocApi 对象,我需要 developerKey
(获取订阅)。
对于授权我需要 login
, password
.
我的决定很糟糕,因为它是一个单例,我需要进行单元测试。我可以更改我的代码吗?
//I GET IT FROM NUGET PACKAGE
using Diadoc.Api;
public sealed partial class DiadocApiFacade
{
private static readonly object _mutex = new object();
private static DiadocApiFacade _instance;
private string _token;
private DiadocApi _api;
private DiadocApiFacade() { }
public static string DefaultUrl => "url was here";
public string DefaultFromBoxId { get; set; }
public DiadocApi Api { get => _api; private set => _api = value; }
public static DiadocApiFacade GetInstance()
{
if (_instance == null)
{
lock (_mutex)
{
if (_instance == null)
{
_instance = new DiadocApiFacade();
}
}
}
return _instance;
}
public string Authenticate(string login, string password, string privateDeveloperKey)
{
if (string.IsNullOrEmpty(login) || string.IsNullOrEmpty(password) || string.IsNullOrEmpty(developerKey))
throw new ArgumentNullException();
Api = new DiadocApi(developerKey, DefaultUrl, new WinApiCrypt());
return _token = _api.Authenticate(login, password);
}
//method for example, >60% methods like that
public Document GetDocument(string messageId, string documentId, string boxId = null)
{
return _api.GetDocument(_token, boxId ?? DefaultFromBoxId, messageId, documentId);
}
}
我假设您想对消耗 DiadocApiFacade
.
依赖倒置来拯救!用接口抽象你的DiadocApiFacade
。使用 工厂模式 来创建对象。下面是一个简单的示例,但如果您需要外观以某种方式运行(例如设置 class 以更改它连接到的位置),您可以扩展工厂。
GetOrCreate
将 return 相同的实例,但如果您在项目中使用依赖项 injection framework(有许多可能满足您的需求),请改用它。
public interface IDiadocApiFacade
{
string Authenticate(string login, string password, string privateDeveloperKey);
public Document GetDocument(string messageId, string documentId, string boxId);
public Document GetDocument(string messageId, string documentId);
}
public class DiadocApiFacadeFactory
{
private static IDiadocApiFacade? _instance = null;
public IDiadocApiFacade Create() //Add parameters
{
return new DiadocApiFacade();
}
public IDiadocApiFacade GetOrCreate()
{
if(_instance == null)
_instance = Create();
return _instance;
}
}
public sealed partial class DiadocApiFacade : IDiadocApiFacade
{
internal DiadocApiFacade() { }
public string Authenticate(string login, string password, string privateDeveloperKey) => string.Empty;
public Document GetDocument(string messageId, string documentId)
=> GetDocument(messageId, documentId, null);
public Document GetDocument(string messageId, string documentId, string? boxId) => new Document();
}
然后你可以使用 [moq)[https://www.nuget.org/packages/moq/] 进行单元测试并伪造 IDiadocApiFacade
[=16 的实现=]