2015년 1월 8일 목요일

[JavaScript] typeof 연산자

피연산자의 데이터 형식을 문자열로 반환하다. 기본 타입과 함수는 각 타입을 식별하는 고유의 문자열을 반환하지만, 배열을 포함한 모든 객체들 'object' 문자열을 반환한다. 때문에, 객체 간의 타입 비교는 사실상 불가능하다.

해당 변수가 객체인지 기본 타입인지를 식별하고자 할 때 사용하며, 객체 간의 타입 비교를 위해서는 instanceof 연산자나 constructor 프로퍼티를 사용하면 된다.

[JavaScript] 배열 관련 메서드들.

자주 사용하는 배열 관련 메서드들을 간단하게 정리해본다. 특히 slice()와 splice()는 사용할 때마다 헷갈린다.

slice와 달리 splice는 해당 배열을 직접 수정한다. 배열의 특정 인덱스에 원소를 추가하거나 교체하고자 한다면 splice()를 사용해야 한다.

2013년 3월 20일 수요일

[iOS] UIWebView를 이용한 로컬 HTML 파일 표시

 iOS 앱 내부에서 웹 페이지를 통해 정보를 전달하려면 UIWebView를 사용하면 된다. URL만 전달하면 UIWebView가 알아서 간단하고 멋지게 웹 페이지를 표시해준다. 그럼, 조건을 하나 추가해서 인터넷이 안되는 오프라인 상태에서도 웹 페이지를 표시하려면 어떻게 해야될까? 답은 간단하다. 필요한 파일들을 전부 앱에 포함시키면 된다. HTML, 자바스크립트, 스타일시트나 이미지 할 것 없이 모두 앱에다 추가하고 UIWebView를 사용하면 된다.

 아래 샘플 프로젝트는 트위터의 부트스트랩(Bootstrap) 프레임워크와 jQuery를 사용하는 간단한 웹 사이트를 UIWebView를 통해 표시하고 있다. 텍스트들은 아무 의미가 없고, Learn more 버튼을 터치하면 다른 페이지로 이동하고 Alert은 알림을 표시하며 Reload는 화면을 새로 고친다. 온라인/오프라인 가리지 않고 잘 작동한다.


상대 경로를 이용한 링크

 특별한 기술이 필요한 건 아니다. 앱에 포함시킬 html 페이지에서 참조되는 모든 로컬 파일들은 상대 경로로 지정한다는 사실만 기억하면 된다. 하위 폴더의 파일에는 "폴더 명/"을, 상위 폴더의 파일에는 ".../" 를 붙여준다. 샘플 프로젝트의 www 폴더에는 두 개의 html 파일과 부트스트랩 폴더가 포함되어 있다. index.html을 살펴보면 알겠지만 각 파일의 경로가 상대 경로를 사용한다는 것을 제외하면 웹 서버에 호스팅되는 일반적인 html 파일과 다를 게 없다.(호스팅되는 html 파일들도 상대경로를 쓴다..-_-;)

새 프로젝트 생성 및 폴더 추가

Single View Application 템플릿을 이용해 새 iOS 프로젝트를 생성한다. 기본으로 생성되는 ViewController 클래스에 UIWebView 아울렛을 추가하고 UIWebViewDelegate 메시지들을 추가해준다. NIB 파일에도 UIWebView를 추가하고 아울렛과 델리게이트를 지정해준다.

프로젝트 네비게이터에서 프로젝트를 선택하고 우 클릭, "Add Files to ..."를 선택한다. 준비한 www 폴더를 선택하고 Destination에 체크, Folders 옵션은 "Create folder references for any added folders"를 선택한다. Add to targets도 체크한다. 프로젝트에 파란색 www 폴더가 추가된다.

UIWebView 설정

viewDidLoad 메시지에 index.html를 요청하는 코드를 추가한다. 번들에 포함된 html 파일의 경로를 이용한 NSURLRequest 객체를 생성해야 한다. 파일 경로 지정 시 추가한 디렉터리 명을 지정해줘야 한다. 기억해 두자.


하이브리드 애플리케이션?

샘플 앱의 화면을 스타일시트를 통해 iOS 기본 UI와 완벽히 똑같이 변경했다고 상상해보자. 사용자가 네이티브 앱 화면인지 웹 화면인지 구분을 할 수 있을까? 실제 PhoneGap과 같은 대다수의 하이브리드 앱 개발 프레임워크들이 이런 방식을 사용한다. 샘플 프로젝트와 원리와 동일하다. HTML/CSS로 이루어진 뷰와 네이티브 코드로 이루어진 컨트롤러 사이를 웹 엔진(= UIWebView)가 연결해주는 방식이다. 샘플이 너무 간단해서 믿기지 않겠지만 사실이다. 샘플 앱에서 "Reload" 버튼을 터치하면 네이티브 앱이 어떤 식으로 반응하는지 확인해보길 바란다.



2013년 3월 15일 금요일

Windows Azure SQL데이터베이스 연결을 위한 NHibernate 설정

Azure 관리자 콘솔에서 알려주는 연결 문자열로는 연결 안된다는게 함정.

hibernate.cfg.xml

2013년 1월 15일 화요일

[iOS] ZBarSDK를 이용한 바코드 리더 개발

ZBarSDK의 적용 및 커스터마이징은 문서화가 잘되어있다. 여기서는 기본적인 사용법만 간단히 기록한다. XCode 4.5 / iOS 6.0 SDK 개발환경에서 iPhone 4S를 이용해 테스트했다.

준비

ZBarSDK 1.2 다운로드

프로젝트 생성 및 ZBarSDK 추가

 Single View Application 템플릿을 이용하여 새 프로젝트를 하나 만든다. 여기서는 ZBarSample을 사용한다. 프로젝트가 생성되면 Project Navigator에서 프로젝트를 선택하고 "Add File to..."를 선택하여 ZBarSDK를 프로젝트에 추가한다. Destination과 Add to targets 옵션을 확인한다.


필요 프레임워크 추가

 TARGETS에서 프로젝트를 선택하고, "Build Phases" 탭의 "Link Binary with Libraries"에 필요한 프레임워크들을 추가한다. 추가해야하는 프레임워크는 다음과 같다.
  • AVFoundation.framework
  • CoreMedia.framework
  • CoreVideo.framework
  • QuartzCore.framework
  • libiconv.dylib



바코드 리더 뷰 추가

 새 UIViewController 클래스를 프로젝트에 추가한다. 이 클래스는 실제 바코드 리더로 사용된다. 여기서는 가장 기본적인 바코드 리더 기능만 구현하기 때문에, ZBarReaderViewController 클래스를 상속받는 것 외에는 별도의 뷰와 코드가 필요가 없다. 바코드 리더 UI를 커스터마이징하려면 이 컨트롤러를 수정해야 한다.

BarcodeReaderController.h
#import <UIKit/UIKit.h>
#import "ZBarReaderViewController.h"

@interface BarcodeController : ZBarReaderViewController

@end



바코드 리더 뷰 호출하기

 ViewController에는 바코드 리더 뷰를 불러올 버튼과 바코드 정보를 처리할 Delegate 메서드가 추가된다. ZBarReaderViewController.h 헤더 파일을 추가하고 ZBarReaderDelegate 프로토콜을 추가한다.

ViewController.h
#import <UIKit/UIKit.h>
#import "ZBarReaderViewController.h"

@interface ViewController : UIViewController <ZBarReaderDelegate>

@end


닙 파일을 통해 버튼과 IBAction을 추가하는 대신 동적으로 버튼을 하나 추가하고 메시지를 하나 선언한다.

ViewController.m
#import "ViewController.h"
#import "BarcodeController.h"

@interface ViewController ()

- (void)scan:(id)sender;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton *scanButton = 
        [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [scanButton addTarget:self
                   action:@selector(scan:)
         forControlEvents:UIControlEventTouchUpInside];
    [scanButton setTitle:@"SCAN" forState:UIControlStateNormal];
    scanButton.frame = CGRectMake(20.0, 40.0, 280.0, 35.0);
    
    [self.view addSubview:scanButton];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}

@end

버튼을 터치하면 BarcodeController가 모달 뷰로 표시된다. 실제 카메라를 사용하므로 시뮬레이터 대신 실제 기기를 통해 실행시켜야 한다.

ViewController.m
#pragma mark - Private methods

- (void)scan:(id)sender
{
    BarcodeController *barcodeController = 
        [[[BarcodeController alloc] init] autorelease];
    barcodeController.readerDelegate = self;
    
    [self presentViewController:barcodeController
                       animated:YES
                     completion:nil];
}


바코드 정보 가져오기

 BarcodeController에 추가로 ZBarReaderDelegate 프로토콜 메서드들을 구현한다. 바코드가 읽히면 imagePickerController:didFinishPickingMediaWithInfo: 메시지가 실행되고 NSDictionary 타입으로 인식된 바코드의 정보를 전달한다.

ViewController.m
#pragma mark - ZBarReaderController methods

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    id<NSFastEnumeration> scanResults =
        [info objectForKey:ZBarReaderControllerResults];
    
    NSString *result;
    
    ZBarSymbol *symbol;
    for (symbol in scanResults)
    {
        result = [symbol.data copy];
        break;
    }
  
    NSLog(@"Result : %@", result);
    
    [result release];
    
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)imagePickerControllerDidCancel:
    (UIImagePickerController *)picker
{
    [self dismissViewControllerAnimated:YES
                             completion:nil];
}


2013년 1월 3일 목요일

[iOS] iPhone 5 확인 매크로

아이폰5 덕분에 개발자가 신경써야 할 일들이 늘었다. 새삼 안드로이드 개발자분들이 존경스러워진다. 아래 코드는 아이폰5를 구분하는 매크로다. 출처는 스택오버플로.
#define IS_IPHONE ( [[[UIDevice currentDevice] model] isEqualToString:@"iPhone"] )
#define IS_IPOD   ( [[[UIDevice currentDevice ] model] isEqualToString:@"iPod touch"] )
#define IS_HEIGHT_GTE_568 [[UIScreen mainScreen ] bounds].size.height >= 568.0f
#define IS_IPHONE_5 ( IS_IPHONE && IS_HEIGHT_GTE_568 )

2012년 12월 13일 목요일

[OSX] 숨긴 폴더 및 파일 표시

터미널을 통해 다음 명령어를 실행한다.
defaults write com.apple.Finder AppleShowAllFiles YES

Finder 강제 종료 후 재실행이 필요하다.

[iOS] Volume Purchasing for Business Program


 어제, 미국에 한해 iOS 앱을 카피 단위로 판매할 수 있는 Volume Purchasing for Business Program(VPP)이 새로 발표됐다. 볼륨 앱 스토어를 통해 2~1000 Copy 단위(Volume)로 앱을 판매/구매할 수 있으며, 구매한 앱은 리딤 코드를 사용하여 앱스토어를 거치지 않고 자체적으로 배포가 가능하다. 아직은 미국 기업에 한정되어 있지만, 곧 한국에도 적용이 될 것이라 생각한다. 개인적인 차원에서도, 신규 사업분야 진출의 일환으로 모바일 사업을 준비 중인 팀 차원에서도 여러모로 큰 도움이 될 것 같다.

* 2013년 1월 현재, 미국 뿐 아니라 호주, 캐나다, 프랑스 등 10개 국가로 확대되었습니다.

[iOS] 루트 뷰 컨트롤러 표시하기

popToRootViewControllerAnimated: 메시지를 이용하면 루트 컨트롤러를 바로 표시할 수 있다.
[self.navigationController popToRootViewControllerAnimated:YES];


미리 알았다면 이런 짓은 안했을텐데.
for (int i = 0; i < [self.navigationController.viewControllers count]; i++) {
     [self.navigationController popViewControllerAnimated:NO];
}

[ASP.NET MVC] IValidatableObject 개체 테스트하기

IValidatableObject 인터페이스를 이용하여 유효성 검사를 수행하는 객체는 Validator 클래스를 통해 테스트할 수 있다. 다음은 테스트 주도 ASP.NET MVC 프로그래밍 책의 예제를 개선한 코드들이다. 참고로 책의 예제에서는 유효성 검사를 위해 커스텀 인터페이스를 사용하고 있다.

public class Todo : IValidatableObject
{
    //[Required]
    //[StringLength(25)]
    public string Title { get; set; }

    public IEnumerable<ValidationResult> Validate(
        ValidationContext validationContext)
    {
        if (string.IsNullOrEmpty(Title))
            yield return new ValidationResult(
                "제목이 입력되지 않았습니다.", 
                new[] { "Title" });

        if (Title != null && Title.Length > 25)
            yield return new ValidationResult(
                "제목이 25자를 초과할 수 없습니다.", 
                new[] { "Title" });
    }
}


제목 길이에 따른 각 개체들의 유효성 검사는 다음과 같이 테스트 한다.
[TestFixture]
public class TodoTest
{
    [Test]
    public void Title_Length_Should_Be_To_Maximum_Of_25_Characters()
    {
        // Arrange
        Todo longTodo = new Todo { Title = "123456789ABCDEF123456789ABCDEF" };
        Todo twentyFiveCharacterTodo = new Todo { Title = "123456789ABCDEF1234567" };
        Todo shortTodo = new Todo { Title = "123456789" };

        // Assert
        Assert.IsFalse(IsValid(longTodo));
        Assert.IsTrue(IsValid(twentyFiveCharacterTodo));
        Assert.IsTrue(IsValid(shortTodo));
    }

    private bool IsValid(IValidatableObject toValidate)
    {
        return Validator.TryValidateObject(
            toValidate, 
            new ValidationContext(toValidate, null, null), 
            null, 
            true);
    }
}


에러 메시지를 확인하고 싶다면 ValidationResult 리스트를 사용하면 된다.
[Test]
public void Title_Length_Should_Be_To_Maximum_Of_25_Characters()
{
    // Arrange
    Todo longTodo = new Todo { Title = "123456789ABCDEF123456789ABCDEF" };

    var result = new List<ValidationResult>();

    Validator.TryValidateObject(
        longTodo,
        new ValidationContext(longTodo, null, null),
        result,
        true);
        
    // Assert
    Assert.AreEqual(1, result.Count);
    Assert.AreEqual("제목은 25자를 초과할 수 없습니다.", result[0].ErrorMessage);
}

2012년 12월 12일 수요일

[ASP.NET MVC] ASP.NET MVC4 테스트 프로젝트에서 MVCContrib 사용 시 예외 발생 해결

ASP.NET MVC4  + MVCContrib 프레임워크를 사용하는 프로젝트들을 테스트하면 MVCContrib의 몇 몇 확장 메서드들이(ShouldMapTo<T>(), AssertActionRedirect<T>()와 같은) 이상한 예외들을 발생시킨다. 동일한 두 개의 타입을 틀린 타입으로 취급한다.

MvcContrib.TestHelper.ActionResultAssertionException : Expected result to be of type RedirectToRouteResult. It is actually of type RedirectToRouteResult.

MVCContrib3에서 참조되는 System.Web.Mvc.dll의 버전(1.0 ~ 3.0)이 테스트 프로젝트에서 참조된 버전(4.0)과 다르기 때문에 발생하는 문제다. App.config를 통해 1.0 ~ 3.0 버전을 강제로 4.0으로 바인딩하여 해결한다. 테스트 클래스 프로젝트에 App.config를 추가하고 다음과 같이 입력해준다.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
                <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="4.0.0.0" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>    
</configuration>

2012년 11월 22일 목요일

[ASP.NET MVC] 인증 필터 적용 여부 테스트

컨트롤러에 적용된 특성(Attribute)들은 리플렉션을 이용해 테스트하면 된다.
Assert.IsTrue(typeof(HomeController)
    .GetCustomAttributes(false)
    .Any(o => o.GetType() == typeof(AuthorizeAttribute)));

2012년 11월 21일 수요일

[ASP.NET MVC] 몇 가지 테스트 케이스들.

ViewResult

액션 메서드의 실행 결과는 ViewResult 클래스를 통해 테스트한다.
[Test]
public void Should_Load_Index_View()
{
    var viewResult = new HomeController().Index() as ViewResult;

    // 뷰 이름 확인
    Assert.AreEqual("Index", viewResult.ViewName);
}


RedirectToRouteResult

POST 액션 메서드의 테스트는 모델 테스트를 포함한다. CRUD 작업 후 처리 방식에 따라 테스트 항목을 결정.
[Test]
public void Should_Delete_Item()
{
    var deleteItem = Items.FindBy("id");
    var redirectToRouteResult = 
        (RedirectToRouteResult)new SampleController().Delete(deleteItem);

    // Item이 제대로 삭제되었는지 확인
    Assert.IsFalse(Items.All.Contains(deleteItem));

    // 삭제 후 Index 뷰가 표시됐는지 확인
    Assert.AreEqual("Index", redirectToRouteResult.RouteValues["action"]);
}


FormCollection

모델 바인딩을 사용할 수 없는 POST 액션 메서드는 FormCollection 클래스를 이용해 테스트.
[Test]
public void Should_Create_Item()
{
    var item = new Item { Id = "1", Name = "Test Item" };

    var formValues = new FormCollection();
    formValues.Add("Id", item.Id);
    formValues.Add("Name", item.Name);

    var controller = new SampleController();
  
    var result = controller.Create(formValues) as RedirectToRouteResult;

    Assert.IsTrue(Items.All.Contains(item));
    Assert.AreEqual("Index", redirectToRouteResult.RouteValues["action"]);
}


.

2012년 11월 20일 화요일

[iOS] UIWebView에서 자바스크립트 실행하기

stringByEvaluatingJavaScriptFromString 메시지를 이용하면 웹페이지의 자바스크립트 코드를 실행하고 반환값을 받을 수 있다. (스크립트)실행 시간이 10초를 넘으면 자동으로 실행 취소가 되며 nil을 반환하니 주의할 것.
// getLayoutStyle 스크립트 메서드를 실행한다.
NSString* returnValue = 
    [self.webView stringByEvaluatingJavaScriptFromString:@"getLayoutStyle"];

2012년 11월 15일 목요일

[iOS] UITableView의 바운스 및 스크롤 오류

UITableView와 UISearchBar를 동시에 사용하면 UITableView의 바운스와 스크롤이 안되는 경우가 있는데, 다음 코드를 viewDidLoad 메서드에 추가하면 해결할 수 있다.

self.tableView.bounces = YES;

참조

[jQuery] XML 파싱


jQuery.parseXML() 메서드를 이용해 xml 문자열을 파싱한다.
        $xml = $($.parseXML(xml))
        $item = $xml.find("item:first");

        alert($(item).text());

[ASP.NET MVC] 브라우저 캐시 회피하기

 현재 개발 중인 모바일 버전 전자결재 서비스의 결재 시나리오다. 사용자가 [문서목록 페이지]에서 문서를 터치하면 [결재 페이지]가 표시된다. 결재 버튼을 터치하면 문서가 결재됐다는 알림과 함께 [문서목록 페이지]를 이동한다. 여기서 웹 브라우저의 'Back' 버튼이 문제가 된다. 'Back' 버튼을 누르면 이미 결재가 완료된 문서이기 때문에 한 단계 더 뒤로 가던가(history.back x 2), 결재가 완료된 문서에 접근했음을 알리는 알림이 필요하다. 우리는 간단히 알림을 제공하도록 [결재 페이지]의 최상단에 다음 스크립트를 입력했다.

     <% if (Model.IsApproved) { %>
        <script type="text/javascript">
                alert("이미 결재가 완료된 문서입니다.");
                document.location.href = "/Approval/List";
        </script>
    <%} %>

하지만 결재 완료 후 'Back' 버튼을 누르면 스크립트는 무시되고 다시 [결재 페이지]가 표시된다. 이미 결재가 완료된 문서이기 때문에 결재, 반려 등의 UI가 표시되는건 문제가 된다. 스크립트가 무시되는 이유는 캐시 때문이다. 캐시에 저장된 웹 페이지가 스크립팅되지 않고 바로 표시되기 때문이다.

캐시 페이지가 아닌 Brand New 페이지를 표시하기 위해 [결재 페이지]의 액션 메서드에 다음 코드를 추가한다.

    // 캐시를 사용하지 않는다.
    Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
    Response.Cache.SetNoStore();

But. 
크롬에서는 정상적으로 작동된다. 문제는 사파리였다. 실제 아이폰 애플리케이션에서는 위의 코드가 전혀 소용이 없다. 'Back' 버튼을 터치하면 캐시된 [결재 페이지]로 이동한다. 반나절을 구글과 StackOverflow를 해집고 돌아다니던 중 이유와 해결 방법을 찾았다. 최신 웹 브라우저들은(크롬은 되던데?) 일반적인 HTTP 캐시와는 차별되는Back/Foward를 위한 별도의 캐시를 제공한다. 이 때문에 위의 코드들이 사파리에서는 작동되지 않았던거다.

해결 방법은 '믿든지 말든지 (StackOverflow의 어느 개발자의 답글이었다. believe it or not.)' body 태그의 unload 이벤트에 빈 핸들러만 등록해주면 된다. 뭐 이런 경우가 있나 싶지만, 자~알 작동한다.이유는 참고 자료의 두 번째 링크를 통해 알 수 있다.

    <body onunload="">


참고

'Microsoft.JET.OLEDB.4.0' 공급자는 로컬 컴퓨터에 등록할 수 없습니다.

System.Data.OleDb.OleDbDataAdapter 클래스를 생성하는데 다음과 같은 예외가 발생했다.

  •  'Microsoft.Jet.OLEDB.4.0' 공급자는 로컬 컴퓨터에 등록할 수 없습니다.
  •  'Microsoft.ACE.OLEDB.12.0' 공급자는 로컬 컴퓨터에 등록할 수 없습니다. 


원인 

구글링 결과 보통 두 가지 이유 때문에 발생하는 예외라 한다. x86 서버에서는 잘 돌아가던 웹 서비스가 x64 서버에서만 예외가 발생하니 아마도 두 번째 이유가 원인인 듯 하다.

  1. 서버에 Office System Driver가 설치되지 않았을 경우 
  2. x64 서버에서 웹 서비스를 호스팅할 경우 


해결 

첫 번째 경우는 Office System Driver를 설치하면 간단하게 해결된다.

 [2007 Office system 드라이버 : 데이터 연결 구성 요소 다운로드] 

두 번째 경우는 등록된 OLE DB Provider가 x64 플랫폼을 지원하지 않기 때문이다. IIS 설정을 변경하거나 프로젝트 빌드 플랫폼 변경을 통해 x86 모듈에 대한 호환성을 추가해준다.

IIS 설정 변경 (IIS7) 
IIS관리자에서 응용 프로그램 풀을 선택. 우 클릭하여 '고급 설정'을 선택한다. '32비트 응용 프로그램 사용'을 'True'로 변경한다.



빌드 플랫폼 변경 (VS2010) 
프로젝트 이름을 클릭하고 우 클릭, '속성'을 선택하여 '빌드'탭의 '플랫폼 대상'을 'x86'으로 변경한다.



2012년 11월 12일 월요일

[MSSQL] DATEPART 함수

DATEPART(datepart, date) 함수를 통해 날짜 별 통계 쿼리 작성이 가능하다. datapart 인수를 통해 년, 월, 주, 일별로 날짜를 뽑아내서 GROUP BY를 수행한다. 자주 잊어버리는 함수라 기록 차원에서 포스팅.


-- 월 별 사용량 통계
SELECT 
    datepart(mm, CREATE_DATE) AS '월', 
    (sum(FILESIZE) / 1024) AS 'MB' 
FROM dbo.EP_FILEINFOT 
WHERE 
    DIRECTORY = 'CONTENTS.GROUP.APPRMAIL_ALL' AND 
    ISDELETED = 'N' AND 
    CREATE_DATE > '2011-01-01'
GROUP BY datepart(mm, CREATE_DATE);

참고자료


  • http://msdn.microsoft.com/en-us/library/ms174420.aspx

2012년 11월 7일 수요일

[ASP.NET MVC] IControllerActivator

ASP.NET MVC 1, 2에서는 사용자 요청을 처리할 컨트롤러를 생성하는 역할을 IControllerFactory 인터페이스가 책임졌다. IContollerFactory 인터페이스는 다음과 같은 역할을 한다.
  1. 요청을 처리할 컨트롤러를 결정
  2. 컨트롤러 생성

이는 클래스 당 한 가지 책임(기능)을 가진다는 단일책임원칙(SRP)에 위배된다. ASP.NET MVC 3 에서는 리팩토링을 통해 IControllerFactory의 역할을 분리하여 IControllerActivator라는 새로운 인터페이스를 추가했다.
  • IControllerFactory : 요청을 처리항 컨트롤러를 결정
  • IControllerActivator : 컨트롤러를 생성

요청을 처리할 컨트롤러가 결정되면 컨트롤러 팩토리 내부에서 IControlerActivator의 Crate 메서드가 호출된다. 사용자 정의 IControllerActivator를 사용하기 위해서는 IDependencyResolver를 통해 새로 구현된 IControllerActivator를 반환하도록 한다.

결론은,
IoC 컨테이너를 사용하려면 커스텀 컨트롤러 팩토리 클래스를 구현할게 아니라 커스텀 DependencyResolver와 ControllerActivator 클래스를 구현해야 한다는 것.


참고