gpt4 book ai didi

c# - 报告代码执行和设计模式?

转载 作者:行者123 更新时间:2023-11-30 17:55:06 24 4
gpt4 key购买 nike

首先,我要感谢大家对 Stack Overflow 社区的持续贡献!多年来,我一直是 Stack Overflow 的成员,并且比任何其他在线资源都更依赖您的意见。尽管我会尽可能地参与并回答成员的问题,但有时我会发现自己陷入困境并需要帮助。

说到这里,我有一个不寻常的代码问题。我正在用 C# 编写一个 API 库,它需要能够从 WPF/Windows 窗体应用程序调用,但也可以从单元测试代码中调用。

问题是我需要能够报告(在 Excel 中)当从 WPF/windows 窗体应用程序中调用 API 时库的每个方法是否正确执行,以及一些其他元数据和可选的返回类型.

当代码在单元测试中使用时,我并不真正关心报告,但我确实需要能够生成关于 API 调用是否正确执行的断言。

例如,如果在单元测试中我们有一个 Test Initialize 部分,其中一个 API 调用可能是创建一个域用户供测试方法使用。另一个也可以创建域组,以便用户具有适当的组成员身份。

为了适应 WPF/WinForms 对 API 的消耗,我一直在重写 API 中的每个函数以返回一个 OperationStep 类型,希望当所有 API 调用都执行后我会有一个我可以编写的 IEnumerable<OperationStep>到 CSV 文件。

所以问题是有没有更简单的方法来实现我目前所做的?考虑到 API 库包含数百种类似的方法,报告对于代码来说极其繁琐且耗时。示例如下所述:

OperationStep<PrincipalContext> createDomainConnectionStep = DomainContext.Current.GetPrincipalContext(settings.DomainInfo);
OperationStep<UserPrincipal> createDomainUserStep = DomainContext.Current.CreateUser(createDomainConnectionStep.Context, settings.TestAccountInfo.Username, settings.TestAccountInfo.Password);
OperationStep<GroupPrincipal> createDomainGroupStep = DomainContext.Current.CreateGroup(createDomainConnectionStep.Context, settings.TestAccountInfo.UserGrupName);

其中 DomainContext 是一个单例对象,其功能是连接到域 Controller 并创建用户、组并将用户关联到组。

请注意,第二个和第三个方法调用都需要第一个方法的输出,因此需要在 public T Context 对象中包含 OperationResult,如下所述。

OperationStep 对象由以下属性组成,这些属性由 IOperation 接口(interface)继承,但 public T Context 除外。

public class OperationStep<T> : IOperation
{
/// <summary>
/// Denotes the Logical Name of the current operation
/// </summary>
public string Name { get; set; }

/// <summary>
/// Denotes the stage of execution of the current operation: Setup, Execution, Validation, Cleanup
/// </summary>
public OperationStage Stage { get; set; }

/// <summary>
/// Denotes whether the test step completed properly or failed.
/// </summary>
public OperationResult Result { get; set; }

/// <summary>
/// Denotes the return type of the test method.
/// </summary>
public T Context { get; set; }

/// <summary>
/// Denotes any other relevant information about the test step
/// </summary>
public string Description { get; set; }

/// <summary>
/// If the test step result is failed, this should have the stack trace and the error message.
/// </summary>
public string Error { get; set; }
}

方法调用本身有点臃肿和乏味,但这里有一个示例。

public class DomainContext
{
private static volatile DomainContext currentContext;
private static object synchronizationToken = new object();

/// <summary>
/// default ctor.
/// </summary>
private DomainContext() { }

/// <summary>
/// Retrieves the Current DomainContext instance.
/// </summary>
public static DomainContext Current
{
get
{
if (currentContext == null)
{
lock (synchronizationToken)
{
if (currentContext == null)
{
currentContext = new DomainContext();
}
}
}
return currentContext;
}
}

/// <summary>
/// Establishes a connection to the domain.
/// </summary>
/// <param name="domainInfo"></param>
/// <returns></returns>
public OperationStep<PrincipalContext> GetPrincipalContext(DomainInfo domainInfo)
{
OperationStep<PrincipalContext> result = new OperationStep<PrincipalContext>();
result.Name = "Establish Connection to Active Directory";
result.Result = OperationResult.Success;
result.Stage = OperationStage.Setup;
result.Description = string.Format("Domain Name: {0}, Default Containter: {1}", domainInfo.FQDN, domainInfo.Container);

try
{
ContextType contextType = this.GetContextType(domainInfo.DomainType);
PrincipalContext principalContext;

try
{
principalContext = new PrincipalContext(contextType, domainInfo.FQDN, domainInfo.Container);
}
catch
{
throw new Exception("Unable to establish connection to Active Directory with the specified connection options.");
}

if (principalContext != null)
{
bool authenticationResult = principalContext.ValidateCredentials(domainInfo.Username, domainInfo.Password);

if (!authenticationResult)
{
throw new Exception("Unable to authenticate domain admin user to Active Directory.");
}

result.Context = principalContext;
result.Result = OperationResult.Success;
}
}
catch(Exception ex)
{
result.Error = ex.Message;
result.Result = OperationResult.Failure;
}

return result;
}
}

理论上,当所有方法调用都已执行时,我应该有一个 IEnumerable<IOperation>,在 win 形式的情况下,我可以将其写入 csv 文件(在 MS Excel 中查看),或者在单元测试的情况下,我可以简单地省略额外信息并忽略(连续执行的方法和 T Context 属性除外)。

最佳答案

如果我没理解错的话 - 所有的 OperationStep 在这里只是为了记录。那么为什么不启用简单的 .NET 日志记录呢?在您方便的地方记录所需信息。您可以使用 TraceSourceDelimetedTraceListener 来写入 .csv 文件。比那更多的。您可以将日志记录逻辑移动到 Strategy 类,并在您的单元测试中覆盖它的日志记录方法,这样您就可以调用 Assert 方法而不是记录日志。

关于c# - 报告代码执行和设计模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15368368/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com