C#:如何重写它而不使用;“复制/粘贴”;代码

C#:如何重写它而不使用;“复制/粘贴”;代码,c#,delegates,copy-paste,C#,Delegates,Copy Paste,我有两种类似的方法: /// <summary> /// /// </summary> /// <param name="domain"></param> /// <exception cref="DomainRecordNotFoundException">Throw when the dns record is not found in Office365</exception>

我有两种类似的方法:

    /// <summary>
    /// 
    /// </summary>
    /// <param name="domain"></param>
    /// <exception cref="DomainRecordNotFoundException">Throw when the dns record is not found in Office365</exception>
    /// <exception cref="DomainNotFoundException">Throw when domain is not added to Office365</exception>
    /// <exception cref="UnknownException">Unknown exception from Microsoft Graph</exception>
    /// <returns></returns>
    public async Task<string> GetMxRecordForDomainAsync(string domain)
    {
        try
        {
            var records = await _graphClient.Domains[domain].ServiceConfigurationRecords.Request().GetAsync();
            string mxRecord = String.Empty;

            foreach (var record in records)
            {
                if (record.RecordType == "Mx")
                {
                    mxRecord = ((Microsoft.Graph.DomainDnsMxRecord)record).MailExchange;
                    break;
                }
            }

            if (String.IsNullOrWhiteSpace(mxRecord))
                throw new DomainRecordNotFoundException(DomainRegistrationCore.Models.DomainRecordType.MX);

            return mxRecord;
        }
        catch (ServiceException graphEx)
        {
            if (graphEx.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                throw new DomainNotFoundException();
            }

            throw new UnknownException(graphEx.StatusCode, graphEx.Error.Message);
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="domain"></param>
    /// <exception cref="DomainRecordNotFoundException">Throw when the dns record is not found in Office365</exception>
    /// <exception cref="DomainNotFoundException">Throw when domain is not added to Office365</exception>
    /// <exception cref="UnknownException">Unknown exception from Microsoft Graph</exception>
    /// <returns></returns>
    public async Task<string> GetVerificationRecordForDomainAsync(string domain)
    {
        try
        {
            var records = (await _graphClient.Domains[domain].VerificationDnsRecords.Request().GetAsync());
            string verificationText = String.Empty;

            foreach (var record in records)
            {
                if (record.RecordType == "Txt")
                {
                    verificationText = ((Microsoft.Graph.DomainDnsTxtRecord)record).Text;
                    break;
                }
            }

            if (String.IsNullOrWhiteSpace(verificationText))
                throw new DomainRecordNotFoundException(DomainRegistrationCore.Models.DomainRecordType.TXT);

            return verificationText;
        }
        catch (ServiceException graphEx)
        {
            if (graphEx.StatusCode == System.Net.HttpStatusCode.NotFound)
            {
                throw new DomainNotFoundException();
            }

            throw new UnknownException(graphEx.StatusCode, graphEx.Error.Message);
        }
    }

其他部分是相同的。我想用一种常用的方法重写它,但不明白怎么写。我假设,我可以使用
Func
Action

来实现这一点。首先,您可以为方法编写一个简化的模式,并分析其结构:

Method1(domain)
  some stuff...
  foreach if(c1) res = (Type1)smth
  if (res == null) throw ex(errMsg1)

Method2(domain)
  some stuff...
  foreach if(c2) res = (Type2)smth
  if (res == null) throw ex(errMsg2)
那么每个函数都有什么功能呢

  • 通用代码(包括foreach循环)
  • “if”语句中的某些特定条件
  • 我们将结果强制转换到的特定类型
  • 当结果为null或空时,用于引发异常的特定错误消息
我们如何满足这些条件并创建一个功能

  • 对于我们名单上的第一名,我们什么都不需要
  • 对于第二个条件,我们可以传递参数,然后在 “如果”条件
  • 第三,我们可以使用泛型并将类型作为类型传递 参数或强制转换结果到
    dynamic
  • 错误消息再次出现,我们可以接受为参数
因此,新方法的简化结构可能如下所示:

Method3<TDomainType>(domain, recordTypeToCheck, errorMsg)
  some stuff...
  foreach if(record.RecordType == recordTypeToCheck) res = (TDomainType)smth
  if (res == null) throw ex with errorMsg 
Method3(域、recordTypeToCheck、errorMsg)
一些东西。。。
foreach if(record.RecordType==recordTypeToCheck)res=(TDomainType)smth
如果(res==null)抛出带有errorMsg的ex

首先定义公共接口

public interface IExtractor
{
    string RecordType { get; }
    string ErrorMessage { get; }
    string GetValue(object record);
}
接下来创建实现

class MxRecordExtractor : IExtractor
{
    public string RecordType => "Mx";

    public string ErrorMessage => DomainRegistrationCore.Models.DomainRecordType.MX;

    public string GetValue(object record)
    {
        return ((Microsoft.Graph.DomainDnsMxRecord)record).MailExchange;
    }
}

class VerificationRecordExtractor : IExtractor
{
    public string RecordType => "Txt";

    public string ErrorMessage => DomainRegistrationCore.Models.DomainRecordType.TXT;

    public string GetValue(object record)
    {
        return ((Microsoft.Graph.DomainDnsTxtRecord)record).Text;
    }
}
稍后创建方法的私有抽象版本:

private async Task<string> ExtractForDomainAsync(string domain, IExtractor extractor)
{
    try
    {
        var records = (await _graphClient.Domains[domain].VerificationDnsRecords.Request().GetAsync());
        string extractedValue = String.Empty;

        foreach (var record in records)
        {
            if (record.RecordType == extractor.RecordType)
            {
                extractedValue = extractor.GetValue(record);
                break;
            }
        }

        if (String.IsNullOrWhiteSpace(extractedValue))
            throw new DomainRecordNotFoundException(extractor.ErrorMessage);

        return extractedValue;
    }
    catch (ServiceException graphEx)
    {
        if (graphEx.StatusCode == System.Net.HttpStatusCode.NotFound)
        {
            throw new DomainNotFoundException();
        }

        throw new UnknownException(graphEx.StatusCode, graphEx.Error.Message);
    }
}
私有异步任务提取器ForDomainAsync(字符串域,IExtractor提取器)
{
尝试
{
var records=(wait _graphClient.Domains[domain].VerificationDnsRecords.Request().GetAsync());
string extractedValue=string.Empty;
foreach(记录中的var记录)
{
if(record.RecordType==提取器.RecordType)
{
extractedValue=提取器.GetValue(记录);
打破
}
}
if(String.IsNullOrWhiteSpace(extractedValue))
抛出新的DomainRecordNotFoundException(extractor.ErrorMessage);
返回提取值;
}
捕获(ServiceException GrapherX)
{
if(graphEx.StatusCode==System.Net.HttpStatusCode.NotFound)
{
抛出新的DomainNotFoundException();
}
抛出新的UnknownException(graphEx.StatusCode,graphEx.Error.Message);
}
}
最后,修改现有方法以使用我们的常用方法:

public Task<string> GetMxRecordForDomainAsync(string domain)
{
    return ExtractForDomainAsync(domain,  new MxRecordExtractor());
}

public Task<string> GetVerificationRecordForDomainAsync(string domain)
{
    return ExtractForDomainAsync(domain, new VerificationRecordExtractor());
}
公共任务GetMxRecordForDomainAsync(字符串域)
{
返回ExtractForDomainAsync(域,新的MxRecordExtractor());
}
公共任务GetVerificationRecordForDomainAsync(字符串域)
{
返回ExtractForDomainAsync(域,新的VerificationRecordExtractor());
}

将RecordType传递给您的方法,并根据它生成条件…如果我们还有一个类型,那么我们的foreach将有一个类型,如果这样:
foreach If(record.RecordType==recordTypeToCheck)res=(TDomainType)smth else If…
public Task<string> GetMxRecordForDomainAsync(string domain)
{
    return ExtractForDomainAsync(domain,  new MxRecordExtractor());
}

public Task<string> GetVerificationRecordForDomainAsync(string domain)
{
    return ExtractForDomainAsync(domain, new VerificationRecordExtractor());
}