'action'에 해당되는 글 2건

Programming/.NET

보통 URL을 생성할때는 다음과 같이 하던게 일반적인 방법이었습니다.

 

<a href="/home/default.htm"></a>

 

그런데 ASP.NET MVC에서 URL을 생성할때는 URL을 생성하는 관련 메서드를 호출함으로서 이루어 집니다.

 

@Html.ActionLink("go""myPage")

 

가장 일반적으로는 @Html 의 ActionLink 헬퍼메서드를 사용하는 것입니다. 만약 이 메서드가 Home컨트롤러의 Index뷰에서 사용되었다면

 

<a href="/home/myPage">go</a>

 

위 형태의 링크를 생성할 것입니다. 이 방법이 사용되는 중요한 이유는 어떤 이유에 의해서 URL의 형태가 바뀌게 되면 사람이 직접 기존의 링크를 수정하지 않아도 해당 라우팅정보가 그대로 반영될 수 있기 때문입니다. 예를 들어 기존에 /Home/Index를 가리키던 라우팅정보가

 

routes.MapRoute("myRoute""myUrl/{action}"new { controller = "Home" });

 

이러한 라우트설정에 의해서 바뀌게 되면 ActionLink메서드는 바뀐 라우팅정보를 수용하여 다음처럼 링크경로를 변경하고 표시할 것입니다.

 

<a href="/myurl/myPage">go</a>

 

이와 같은 작동방식은 액션메서드의 속성에 라우트정보가 정의되어 있는 상태에서도

 

[Route("~/Default")]
public ActionResult MyPage()
{
    return View();
}

 

동일하게 라우팅정보를 적용시켜 아래와 같은 형태의 URL을 생성하게 됩니다.

 

<a href="/Default">go</a>

 

ActionLink 메서드는 기본적으로 현재의 컨트롤러내부를 가리키게 되는데 만약 다른 컨트롤러의 액션메서드를 호출하고자 한다면

 

@Html.ActionLink("go""myPage""myControl")

 

예제에서 처럼 직접 컨트롤러를 지정하면 됩니다.

 

<a href="/myControl/myPage">go</a>

 

컨트롤러와 액션이외에 특정 세그먼트와 값을 추가적으로 전달해야할 경우도 있는데 이럴때는 익명 형식을 통해 해당 세그먼트와 그 값을 정의해 두면 됩니다.

 

@Html.ActionLink("go""myPage"new { id = "cliel" })
<a href="/Home/myPage/cliel">go</a>

 

이렇게 처리될 수 있는 이유는 기본적으로 라우트정보가 설정되는 RouteConfig.cs 파일에 다음과 같이 라우트정보가 정의되어 있기 때문입니다.

 

routes.MapRoute(
    name"Default",
    url"{controller}/{action}/{id}",
    defaultsnew { controller = "Home"action = "Index"id = UrlParameter.Optional }
);

 

만약 id 세그먼트에 대한 정의가 라우정보에 존재하지 않았을때 같은 방식으로 ActionLink 메서드를 사용하게 되면 id는 세그먼트가 아닌 단순한 get값을 추가해 줍니다.

 

<a href="/Home/myPage?id=cliel">go</a>

 

ActionLink는 단순히 우리가 필요한 링크를 만들 수 있을 뿐만 아니라 HTML표현에 필요한 여러가지 속성들을 설정할 수도 있습니다.

 

@Html.ActionLink("go""myPage"nullnew { id = "mylink"@class = "mystyle" })
<a class="mystyle" id="mylink" href="/Home/myPage">go</a>

 

익명형식으로 설정할 속성의 이름과 속성값을 지정하고 있는데 참고로 ASP.NET MVC에서는 C#에서 특정한 예약어를 사용해야할때 앞에 @문자를 붙여 쓸 수 있습니다. 예제에서 class의 속성을 설정하기 위해 @class로 표현한것은 바로 이때문입니다.

 

물론 이외에도 다음과 같이 필요한 모든 값을 ActionLink에 전달하면 링크가 생성되는 형태를 세부적으로 다룰 수 있습니다.

 

@Html.ActionLink("go""myPage""Home""https""www.naver.com""target"new { id = "cliel" } ,new { id = "mylink"@class = "mystyle" })
<a class="mystyle" id="mylink" href="https://www.naver.com/Home/myPage/cliel#target">go</a>

 

ActionLink 메서드와 비슷하게 Action 메서드도 존재하는데 이 메서드는 링크를 생성하는게 아닌 http://cliel.com/Home/Index 와 같은 단순한 문자열만을 생성합니다.

 

뿐만 아니라 URL은 특정 라우트를 대상으로 URL을 생성할 수도 있어서 예를 들어 RouteConfig.cs 파일에 기본적으로 다음과 같은 등록된 라우트정보가 있다면

 

@Html.RouteLink("go""Default"new { id = "cliel" })

 

위와 같이 라우트명을 지정해 URL을 해당 라우트를 기반으로 하여 생성할 수 있습니다.

 

/Home/Index/cliel

 

RouteLink 메서드에서는 별도의 컨트롤러와 메서드를 지정하지 않았지만 이는 라우트에 등록된 기본값으로 대체될 수 있고 id세그먼트는 지정된 값으로 대체될 수 있기 때문입니다.

 

이제 까지살펴본 ActionLink 메서드는 뷰에서 사용이 가능한 메서드인데 때로는 컨트롤러내부에서 URL을 생성해야할 필요가 있습니다. 이럴때는 Url 객체의 Action 과 RouteUrl 메서드를 사용할 수 있습니다.

 

string url = Url.Action("Index""Home"new { id = "cliel" });

 

우선 Action 메서드는 ActionLink 메서드와 사용법이 완벽히 일치하므로 별다른 설명이 필요없을 것입니다.

 

string url = Url.RouteUrl(new { controller = "Home"action = "MyPage" });

 

RouteUrl 메서드는 RouteConfig.cs 에서 라우트를 설정할때와 비슷한 개념과 방식으로 URL을 생성할 수 있습니다.

'Programming > .NET' 카테고리의 다른 글

Debug / Release  (0) 2019.01.15
[ASP.NET MVC] Razor  (0) 2019.01.08
[ASP.NET MVC] URL 다루기  (0) 2018.12.18
[C#] 비트(bit) 연산자  (0) 2018.11.20
[ASP.NET MVC] 액션 메서드(Action Method)  (0) 2018.11.13
[C#] Thread  (0) 2018.11.06
0 0
Programming/.NET

람다식은 수학에서의 람다대수형식을 C#언어의 문법으로 표현한것입니다. 람다식을 사용하면 기존의 길고 복잡했던 구문을 간소화하고 단순화시킬 수 있습니다.

 

예를 들어 익명메서드를 사용한 하나의 예를

 

delegate int callMethod(int iint j);

static void Main(string[] args)
{
    callMethod cm = delegate (int iint b)
    {
        return i + b;
    };

    Console.Read();
}

 

람다식으로 표현하면 다음과 같이 할 수 있습니다.

 

delegate int callMethod(int iint j);

static void Main(string[] args)
{
    callMethod cm = (ib) => i + b;

    Console.Read();
}

 

우선 callMethod 타입에서는 델리게이트 선언으로 인해 델리게이트형식의 익명메서드, 그리고 해당 메서드에 int형 매개변수 2가 전달된다는 것을 알 수 있습니다. 따라서 deleteage와 int형식은 다음과 같이 생략할 수 있습니다.

 

delegate (int i, int b) -> (i, b)

 

그리고 이 생략된 표현이 람다식임을 => 문자로 알려줍니다.

 

람다식 표현에서 반환값이 없는 경우에는 중괄호({})가 있어야 하지만 반환값이 존재하는 경우에는 return과 해당 부분을 감싸는 중괄호가 생략될 수 있기에 최종적으로 다음과 같은 표현이 완성됩니다.

 

(i, b) => i + b;

 

callMethod cm = (ib) => i + b;
Console.WriteLine(cm(100, 200));

 

예제에서는 람다식으로 델리게이트를 사용해 익명 메서드를 구현하고 있습니다. 이것은 일반적인 익명 메서드도 마찬가지지만 람다식으로 익명 메서드를 구현하기 위해서는 일일이 델리게이트를 선언해야 한다는 것을 의미합니다. 이런 불편함을 감소시키고자 .NET에서는 델리게이트의 일부 형식을 구현한 Action과 Func를 마련해 두었습니다.

 

static void Main(string[] args)
{
    Action<int> a_i = (i) => { Console.WriteLine("number : {0}"i)};
    a_i(100);

    Console.Read();
}

 

먼저 Action은 반환값이 없는 익명메서드를 구현하는데 사용됩니다. Action에 보시면 매개변수로 받을 수 있는 데이터형식을 <int>로 정의했는데 이것은 Action<T>로 제네릭화 되어있다는 것을 알 수 있습니다. 이런 사항은 Func도 마찬가지입니다.

 

Func<intintint> cal = (ij) => i + j;
int sum = cal(100, 200);
Console.WriteLine(sum);

 

Func는 반환값이 있는 경우에 사용할 수 있습니다. 예제에서 Func는 매개변수 데이터 형식으로 int형 3개가 존재하는데 처음 2개는 i와 j에 대응되고 나머지 하나는 반환형식에 해당합니다.

 

Action과 Func사용시 매개변수는 최대 16개까지 유동적으로 사용할 수 있습니다.

 

람다식은 익명메서드를 구현하는것 뿐만 아니라 컬렉션에도 적용할 수 있습니다. 예를 들어

 

List<int> l = new List<int{ 1, 2, 3, 4, 5 };

 

위와 같은 List의 경우 각 요소를 순회하려면 다음과 같이 할 수 있지만

 

foreach (int i in l)
    Console.WriteLine(i);

 

Action 람다식을 적용하면

 

l.ForEach((el) => { Console.WriteLine(el)});

 

이와 같이 처리할 수 있습니다. 예제를 보면 컬렉션의 ForEach메서드를 사용하는데 이 메서드는 Action<T>타입을 받으므로 람다식의 Action을 전달하면 됩니다.  다음 예제는 ForEach의 또 다른 처리방식을 보여주고 있습니다.

 

Array.ForEach(l.ToArray()(el) => { Console.WriteLine(el)});

 

Action은 리턴값을 가지지 않는다고 하였습니다. 따라서 특정 조건에 해당하는 요소만을 반환받으려면 Func를 사용할 수 있습니다.

 

List<int> r = l.FindAll((el) => el > 3);
r.ForEach((el) => { Console.WriteLine(el)});

 

이때 메서드는 FindAll을 사용하며 Func를 구현하는 람다식을 통해 3보다 큰 값만 가져오도록 하였습니다. FindAll과 비슷한 메서드로 Where도 존재하는데

 

IEnumerable<int> r = l.Where((el) => el > 3);
Array.ForEach(r.ToArray()(el) => { Console.WriteLine(el)});

 

이때 Where는 List가 아닌 IEnumerable형식으로 결과를 반환합니다. IEnumerable은 자체적인 ForEach메서드를 지원하지 않으므로 Array의 ForEach를 호출해 결과요소를 반환받아야 합니다. 이때 만약 반환되는 데이터 타입을 달리해야 한다면 Select를 사용할 수 있습니다.

 

IEnumerable<double> r = l.Select((el) => double.Parse((el > 3).ToString()));

 

FindAll과 Where메서드는 결과는 같지만 동작방식은 약간 다른데 Where메서드는 호출되는 즉시 동작하지 않고 ForEach로 배열순회가 되서야 실행이 됩니다. 이를 지연된 평가라고 하는데 이때문에 요소를 임의적으로 정리만 해준다면 Where에서 다루어지는 요소가 전체가 아닌 일부만으로 처리될 수 있기에 성능적으로 도움이 될 수 있습니다.

 

위 예제에서 사용된 Select도 마찬가지인데 이는 ConvertAll에서 지연된 평가를 위해 만들어진 메서드입니다. 이처럼 람다식자체는 메서드나 컬렉션에서 특정 연산을 위해 사용될 수 있습니다.

 

이 외에도 람다식은 식자체를 데이터로서 취급하는 방법이 존재합니다. 예를 들어 Func에 관한 람다식을 데이터로 하려면

 

Expression<Func<intintint>> exp = (ij) => i + j;

 

위와 같이 할 수 있습니다. Expression<T>에서 T는 식에 해당하는 델리게이트타입이 전달되며 exp가 식을 담고 있는 변수에 해당합니다. 따라서 Expression 개체는 다음 형태처럼 구문에 대한 개별적인 표현이 가능합니다.

 

Expression<Func<intintint>> exp = (ij) => i + j;

BinaryExpression be = (BinaryExpression)exp.Body;
Console.WriteLine(be.ToString());

 

exp에서 Body는 식의 본체를 의미하고 이를 출력해 보면 (i + j)라는 내용을 확인할 수 있습니다. 그런데 반대의 경우도 가능해서 Expression을 통해 식을 구성할 수도 있습니다.

 

ParameterExpression Lpe = Expression.Parameter(typeof(int)"i");
ParameterExpression Rpe = Expression.Parameter(typeof(int)"j");

BinaryExpression plusBe = Expression.Add(Lpe, Rpe);

Expression<Func<intintint>> exp = Expression<Func<intintint>>.Lambda<Func<intintint>>(plusBe, new ParameterExpression[] { Lpe, Rpe });

 

좌항과 우항을 ParameterExprsssion으로 구성하고 BinaryExpression을 통해 2항 연산에 관한 식을 정의합니다. 이때 Expression의 Add 메서드를 통해 +연산자를 적용한뒤 연산자와 각항을 구성하고 Lamda메서드로 전체식을 구성합니다. 물론 BinaryExpression외에도 루프를 표현하는 LoopExpression이나 상수식을 표현하는 ConstantExpression등 구성할 수 있는 다양한 타입의 식이 존재합니다.

 

Console.WriteLine(exp.ToString());
Func<intintint> f = exp.Compile();
Console.WriteLine(f(10, 20));

 

위에서 처럼 식을 데이터로서 취급하면서도 컴파일과정을 통해 실제 실행가능한 코드로 동작시킬 수도 있습니다.

 

Expression<Func<intintint>> exp = (ij) => i + j;

Func<intintint> f = exp.Compile();
Console.WriteLine(f(10, 20));

 

식을 데이터로서 다루고자 하는 이러한 방법은 프로그램이 동작하는 시점에 필요한 처리로직을 동적으로 생성하고 실행할 수 있다는 것인데 사실 잘 쓰이지는 않는 방법입니다. 그냥 이런게 가능하다는 것만 알아두고 넘어가도 좋을듯 합니다.

 

참고로 람다식을 이용하면 익명메서드와 비슷하게 단일문의 메서드를 생성할 수 있습니다.

 

static void Main(string[] args)
{
    int sum = plus(10, 20);

    Console.Read();
}

static int plus(int iint j) => (i + j);

 

plus메서드는 2개의 매개변수값을 받아 하나의 결과를 반환하는 단일문으로 메서드가 구현되었습니다.

0 0
1
블로그 이미지

클리엘