C #: как переписать его без кода «копировать / вставить» - PullRequest
0 голосов
/ 23 января 2019

У меня есть 2 аналогичных метода:

    /// <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);
        }
    }

Как мы видим, эти 2 метода отличаются только этой частью:

        foreach (var record in records)
        {
            if (record.RecordType == **RECORD**)
            {
                mxRecord = ((**TYPE_OF_RECORD**)record).MailExchange;
                break;
            }
        }

        if (String.IsNullOrWhiteSpace(mxRecord))
            throw new DomainRecordNotFoundException(**RECORD**);

остальные части такие же.Я хочу переписать его для одного распространенного метода, но не понимаю, как.Я предполагаю, что я могу сделать это с Func<> или Action<>

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Сначала определите общий интерфейс

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);
    }
}

Наконец измените существующие методы наиспользуйте наш общий метод:

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

public Task<string> GetVerificationRecordForDomainAsync(string domain)
{
    return ExtractForDomainAsync(domain, new VerificationRecordExtractor());
}
0 голосов
/ 23 января 2019

Ну, вы могли бы сначала записать упрощенную схему для методов и проанализировать их структуру:

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'
  • Специальный тип, к которому мы приводим результат в
  • Конкретное сообщение об ошибке, которое мы используем для исключения, которое мы генерируем в случае, когда результат равен нулю или пуст

Как мы можем выполнить эти условия и создать одну функцию?

  • Для номера один в нашем списке нам ничего не нужно
  • Для второго условия мы можем передать аргумент, который мы затем используем в условии 'if'.
  • В-третьих, мы можем использовать обобщенные типы и передавать тип в качестве параметра типа или приводить результат к dynamic
  • . Сообщение об ошибке снова можно принять в качестве параметра

. Таким образом, упрощенная структурановый метод может выглядеть так:

Method3<TDomainType>(domain, recordTypeToCheck, errorMsg)
  some stuff...
  foreach if(record.RecordType == recordTypeToCheck) res = (TDomainType)smth
  if (res == null) throw ex with errorMsg 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...