본문 바로가기

.NET/C#

C# Universal String Parsing Utility

http://www.codeproject.com/Tips/434173/Csharp-Universal-String-Parsing-Utility


위에서 퍼온 글입니다.


The Problem

tryParse()을 이용해서 string 을 다른 타입으로 파싱하는 일은 참 나를 고통으로 몰고 있다. 그리고 결과코드도 지저분하다. 

var someStringThatShouldBeAnInt = "10";
int i = 0;
if(int.TryParse(someStringThatShouldBeAnInt, out i))
{
    //Continue on with things
}else
{
    //Complain about it
}


The Desired Solution

지저분한것들을 추상화하고 그것을 아래와같이 대체한다.: 

var someStringThatShouldBeAnInt = "10";
var i = someStringThatShouldBeAnInt.Parse<int>();


The How

Reflection을 사용하여 tryParse() 을 갖는 모든 타입들은 동적으로 그 함수를 호출할수 잇게 하는것이다.

public static T Parse<T>(this string thingToParse)
{
    var retType = typeof(T);
    var tParse = retType.GetMethod("TryParse",
                                   BindingFlags.Public | BindingFlags.Static, null,
                                   new[] { typeof(string), retType.MakeByRefType() }, null);

    if (tParse != null)
    {
        var parameters = new object[] { thingToParse, null };
        var success = (bool)tParse.Invoke(null, parameters);
        if (success)
        {
            return (T)parameters[1];
        }
    }

    return default(T);
}


만약 컨버팅하고자 하는 타입이 tryParse()를 구현안했다면 어떻게 하지?

var csv = "1,2,3,4,5,6,7";
var list = someStringThatShouldBeAnInt.Parse<List<string>>();


위의 코드는 동작하지 않을것입니다. 그리하여 converter에게 옵션을 제공을 하도록했습니다.

public static T Parse<T>(this string thingToParse, Func<string, T> parser)
{
    return parser.Invoke(thingToParse);
}


깔끔하죠?. 이제 다음과 같은 코드가 가능합니다:


var csv = "1,2,3,4,5,6,7";
var list = csv.Parse<List<string>>(x => x.Split(',').ToList());