2012-12-28 2 views
1

공용 소비자 사이트와 소비자 대면 사이트 관리를위한 관리 영역이있는 Autoface를 사용하여 새 MVC4 사이트를 만들고 있습니다. 관리 사이트는 소비자 대면 사이트와 동일한 서비스를 사용하지만 사용자 정의 브랜딩 기능이없는 다른 지역에 위치합니다.영역 당 자동 종속성

필자는 다른보기에서 사용할보기에 대한 공유 데이터 세트를 제공하는 ViewDataFactory가 있다는 조언을 따랐습니다. 내 목표는 당신이 어떤 지역에 따라 다른 ViewDataFactory을 제공하는 것입니다.

그래서 예를 들어, 여기이 나에게주는 내 모든 컨트롤러에 주입 한 ViewFactory의를 IViewDataFactory

builder.RegisterType<SelfServiceViewDataFactory>().As<IViewDataFactory>(); 

를 구현하는 서비스입니다 . 그러나 제가 acheive려고하는 것은이 (작동하지 않는 코드) 같은 것입니다 :

builder.RegisterType<ViewDataFactory>().As<IViewDataFactory>().ForType(ControllerBase1);  
builder.RegisterType<DifferentViewDataFactory>().As<IViewDataFactory>().ForType(ControllerBase2);  

경우 컨트롤러 유형이나 해결되는 서비스를 확인 할 것 MVC 영역입니다.

편집은

내 게시물이 두 가지 질문이 명확하게

:

  1. 는 X 형의 클래스에 대해 "말을 Autofac있는 방법이 있나요를 입력 Y의 서비스가 제공됩니다 인스턴스 Z "?
  2. 구성 요소가 사용되는 영역을 기준으로 Autofac 동작을 변경하는 방법이 있습니까?

# 1에 대한 답을 읽고있는 모든 항목 중 공급할 구성 요소를 확인하는 데 사용할 매개 변수가 없다면 "아니오"인 것 같습니다. Ninject가 네임 스페이스에 기반한 의존성을 제공 할 수 있으므로 다른 프레임 워크가이 경우를 처리하는 것 같습니다. 해결책은 매개 변수를 제공하거나 두 개의 서로 다른 서비스를 정의하는 것입니다.

Autofac 및 MVC 영역에 대한 많은 논의를 보지 못했지만 # 2는 사용자 지정 솔루션 없이는 불가능합니다. 감사!

+0

Essentiall y, 당신은 지역별 참조의 분리 된 콘테이너를 가진 모듈 디자인이있을 것입니다, 정확합니까? –

+0

예. 영역 당 Autofac 컨테이너를 설정하는 방법이 있습니까? – AlexT

+0

그들이 서로 다른 것들을하고 있다면 실제로 두 가지 구체적인 클래스를 모두'IViewDataFactory'에 넣고 싶습니까? ViewDataFactory에 의존하는'ControllerBase1'과'DifferentViewDataFactory'에 의존하는'ControllerBase2'도 마찬가지입니다 – wal

답변

2

명명 된 서비스를 사용하는 것이 가장 좋습니다. 그래서 당신은 같은 것을 할 거라고 :

builder 
    .RegisterType<ViewDataFactory>() 
    .Named<IViewDataFactory>("Area1");  

builder 
    .RegisterType<DifferentViewDataFactory>() 
    .As<IViewDataFactory>("Area2"); 

을 그리고 당신은 수동으로 컨트롤러를 등록하지 않으려합니다.

넣어 어딘가에 세계적으로 접근이 속성 :

public class ServiceNamedModule : Module 
{ 
    protected override void AttachToComponentRegistration(
     IComponentRegistry registry, IComponentRegistration registration) 
    { 
     registration.Preparing += 
      (sender, args) => 
      { 
       if (!(args.Component.Activator is ReflectionActivator)) 
        return; 

       var namedParameter = new ResolvedParameter(
        (p, c) => GetCustomAttribute<ServiceNamedAttribute>(p) != null, 
        (p, c) => c.ResolveNamed(GetCustomAttribute<ServiceNamedAttribute>(p).Name, p.ParameterType)); 

       args.Parameters = args.Parameters.Union(new[] { namedParameter }); 
      }; 
    } 

    private static T GetCustomAttribute<T>(ParameterInfo parameter) where T : Attribute 
    { 
     return parameter.GetCustomAttributes(typeof(T), false).Cast<T>().SingleOrDefault(); 
    } 
} 

을 그리고 :

[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] 
public class ServiceNamedAttribute : Attribute 
{ 
    private readonly string _key; 

    public ServiceNamedAttribute(string key) 
    { 
     _key = key; 
    } 

    public string Key { get { return _key; } } 
} 

당신의 Autofac의 설정이 모듈을 추가 당신은 그냥 함께 자갈길과 테스트되지 않은 코드를 사용할 수 있습니다 다음과 같이 생성자를 꾸미면 컨트롤러를 자동 등록 할 수 있습니다.

public class Controller1 
{ 
    public Controller1(ServiceNamed["Area1"] IViewDataFactory factory) 
    { ... } 
} 
+0

감사합니다. 명명 된 서비스를 조금 살펴 봐야 할 것입니다. 그 이름을 가진 컨테이너를 명시 적으로 컨테이너에 요구하지 않고 어떻게 사용할 지 확신하지 못했습니다. name 속성 클래스는 흥미로운 방법입니다. – AlexT

+0

속성을 추가하고 싶지 않고 클래스의 네임 스페이스를 사용하려면'Preparing' 이벤트 핸들러에서 할 수 있어야합니다. 그냥'args'의 적절한 속성을 찾으십시오. –