>  기사  >  백엔드 개발  >  .NET 코드 리팩터링 기억하기(2부)

.NET 코드 리팩터링 기억하기(2부)

黄舟
黄舟원래의
2017-02-06 14:40:291199검색

public override bool TryGetMember(GetMemberBinder binder, out object result)
{
            if (!_dictionary.TryGetValue(binder.Name, out result))
            {
                result = null;
                return true;
            }
            var dictionary = result as IDictionary<string, object>;
            if (dictionary != null)
            {
                result = new DynamicJsonObject(dictionary);
                return true;
            }
            var arrayList = result as ArrayList;
            if (arrayList != null && arrayList.Count > 0)
            {
                if (arrayList[0] is IDictionary<string, object>)
result = new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)));
                else
                    result = new List<object>(arrayList.Cast<object>());
            }
            return true;
        }
    }
    #endregion
}

다음 단계는 GetContent 방법입니다. 이 방법의 목적은 이전에 고객이 전달한 템플릿 변수 매개변수 키-값 쌍과 SMS 템플릿 콘텐츠를 기반으로 최종 SMS 전송 콘텐츠를 조합하는 것입니다. , 이 방법은 하드 코딩되어 있으므로 이제 동적 획득으로 변경해야 합니다.

문자 메시지 템플릿 내용 예시:

【一应生活】您有一件单号为expressNumbers company,已到communityName收发室,请打开一应生活APP“收发室”获取取件码进行取件。
点击下载http://a.app.qq.com/o/simple.jsp?pkgname=com.ening.life

해당 템플릿의 내용에 문제가 있다는 것을 발견했습니다. 문자 메시지 내용에 가끔 영어 단어가 있을 수 있으므로 모든 변수 매개변수에 {}를 추가하겠습니다. 수정 내용은 다음과 같습니다.

【一应生活】您有一件单号为{expressNumbers} {company},已到{communityName}收发室,
请打开一应生活APP“收发室”获取取件码进行取件。点击下载http://a.app.qq.com/o/simple.jsp?pkgname=com.ening.life

SMS 템플릿의 변수 매개변수를 고객이 전달한 개체를 기준으로 가변 매개변수에 해당하는 값으로 바꿔야 합니다. 그런 다음 먼저 이 객체의 키-값 쌍 정보를 구문 분석해야 합니다.

  /// 把object对象的属性反射获取到字典列表中
        /// </summary>
        /// <param name="data">object对象</param>
        /// <returns>返回Dictionary(属性名,属性值)列表</returns>
         static Dictionary<string, string> GetProperties(object data)
        {
            Dictionary<string, string> dict = new Dictionary<string, string>();

            Type type = data.GetType();
            string[] propertyNames = type.GetProperties().Select(p => p.Name).ToArray();
            foreach (var prop in propertyNames)
            {
                object propValue = type.GetProperty(prop).GetValue(data, null);
                string value = (propValue != null) ? propValue.ToString() : "";
                if (!dict.ContainsKey(prop))
                {
                    dict.Add(prop, value);
                }
            }
            return dict;
        }

다음 단계는 정규 표현식을 통해 문자 메시지 템플릿 콘텐츠를 일치시키는 것입니다.

  /// 多个匹配内容
        /// </summary>
        /// <param name="sInput">输入内容</param>
        /// <param name="sRegex">表达式字符串</param>
        /// <param name="sGroupName">分组名, ""代表不分组</param>
        static List<string> GetList(string sInput, string sRegex, string sGroupName)
        {
            List<string> list = new List<string>();
            Regex re = new Regex(sRegex, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline);
            MatchCollection mcs = re.Matches(sInput);
            foreach (Match mc in mcs)
            {
                if (sGroupName != "")
                {
                    list.Add(mc.Groups[sGroupName].Value);
                }
                else
                {
                    list.Add(mc.Value);
                }
            }
            return list;
        }
        public static string ReplaceTemplate(string template, object data)
        {
            var regex = @"\{(?<name>.*?)\}";
            List<string> itemList = GetList(template, regex, "name"); //获取模板变量对象
            Dictionary<string, string> dict = GetProperties(data);
            foreach (string item in itemList)
            {
                //如果属性存在,则替换模板,并修改模板值
                if (dict.ContainsKey(item))
                {
                    template = template.Replace("{"+item+"}", dict.First(x => x.Key == item).Value);
                }
            }
            return template;
}

이런 방식으로 고객이 전달한 개체는 구문 분석 코드에서 분리됩니다. 고객이 전달한 개체는 더 이상 코드 구현에 의존하지 않고 데이터의 템플릿 콘텐츠 구성에 따라 달라집니다. 테이블.

이 메소드를 작성하고 원하는 효과가 있는지 확인하기 위해 단위 테스트를 실행하겠습니다. 안타깝게도 이 프로젝트에서는 단위 테스트가 전혀 사용되지 않습니다. 직접 단위 테스트

[TestClass]
    public class MatchHelperTest
    {
        [TestMethod]
        public void ReplaceTemplate()
        {
            //模板文本
            var template = "【一应生活】您有一件单号为{expressNumbers} {company},已到{communityName}收发室,
            请打开一应生活APP“收发室”获取取件码进行取件。点击下载http://a.app.qq.com/o/simple.jsp?pkgname=com.ening.life";
            //数据对象
            var data = new { expressNumbers = "2016", company = "长城", communityName = "长怡花园"};
            string str = "【一应生活】您有一件单号为2016 长城,已到长怡花园收发室,
            请打开一应生活APP“收发室”获取取件码进行取件。点击下载http://a.app.qq.com/o/simple.jsp?pkgname=com.ening.life";
            string str1=MatchHelper.ReplaceTemplate(template, data);

            Assert.AreEqual(str1,str);

            //重复标签的测试
            template = "【一应生活】您有一件单号为{expressNumbers} {company},已到{communityName}收发室,单号:{expressNumbers}";
            str = "【一应生活】您有一件单号为2016 长城,已到长怡花园收发室,单号:2016";
            str1=MatchHelper.ReplaceTemplate(template, data);
            Assert.AreEqual(str1, str);
        }
    }

단위 테스트에 관해 말하자면, 여러 가지 이유로 많은 회사에서 사용하지 않는 것 같습니다. 또한 사업이 단순하면 단위 테스트를 작성할 필요가 없다고 생각합니다.중국의 많은 기업가들은 프로젝트 진행 속도가 매우 빠릅니다. 단위 테스트 작성에 시간이 걸리지 않는다고 하면 확실히 거짓말입니다. 단위 테스트를 작성하면 성능이 향상될 수 있습니다. 개발 효율성과 재작업률 감소는 개인적으로 말하기 어렵습니다. 단위 테스트를 작성하지 않더라도 다른 방법으로 보완할 수 있기 때문입니다. 개인적인 생각이니 비난하지 마세요.

컨트롤러가 비즈니스 로직 코드를 이렇게 직접 호출하는 것으로 밝혀졌습니다

public string GetContent(dynamic messageContext)
{
            string strMsg = "";
            string TypeCode = string.IsNullOrEmpty(messageContext.serviceCode) ? "001" : messageContext.serviceCode;
            string channel = messageContext.channel;
            try{
var Module = unitOfWork.MessageModule.Get(c => c.Type == channel && c.TypeNo == TypeCode).FirstOrDefault();
                if (!string.IsNullOrEmpty(Module.Content))
                {
                    var content = Module.Content;
                    strMsg = MatchHelper.ReplaceTemplate(content, messageContext);
                }
                return strMsg;
            }
            catch (Exception ex)
            {
                strMsg = ex.Message;
            }
            return strMsg;
        }

구체적인 클래스의 구현에 따라 달라지며, 구상은 불안정하다는 것을 우리는 알고 있습니다. 추상화는 안정적이려면 인터페이스를 향해 프로그래밍해야 합니다. 오늘은 문자 메시지를 보내고, 내일은 이메일을 보내거나 로그 기록을 추가하는 등의 작업을 할 수 있습니다.

MessageModuleBusiness message
ModuleBusiness = new MessageModuleBusiness()

그런 다음 호출 코드는

public interface IMessageModuleBusiness
{
        /// <summary>
        /// 组装消息内容
        /// </summary>
        /// <param name="messageContext">动态参数对象</param>
        /// <returns>组装后的消息内容</returns>
        string GetContent(dynamic messageContext);
}

로 수정됩니다. 최종 externalMerchantSendMessage 코드는

private IMessageModuleBusiness message
ModuleBusiness = new MessageModuleBusiness();

이 경우 리플렉션을 통해 다시 분리하는 것이 편리합니다. IOC는 미래에

이 단계별 재구성을 통해 고객의 템플릿 매개변수 변수가 변경될 때 원래 테이블 구조를 수정하지 않고 고객 호출에 영향을 주지 않고 변경 사항을 캡슐화했습니다. 변경하면 코드를 변경할 필요가 없으며 테이블의 템플릿 내용만 수정하면 됩니다.


리팩토링할 때 클래스 다이어그램을 그리는 것은 매우 좋은 습관입니다. 코드 구조가 한눈에 보입니다.

위 내용은 .NET 코드 재구성(2부) 내용입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!

.NET 코드 리팩터링 기억하기(2부)

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.