2013-11-26 2 views
0

나는 약간의 시간을 보냈으며,이 시나리오에서는 분명한 해결책이없는 것 같습니다.성 윈저 라이프 스타일 구성

난 내가 할 수없는, 내가 그 개체 중 하나에 대해 서로 다른 라이프 스타일을 사용하려면

public static void RegisterAllFromAssemblies(string a) 
    { 
     IoC.Container.Register(
      AllTypes.FromAssemblyNamed(a) 
       .Pick() 
       .WithService.FirstInterface() 
       .Configure(o => o.LifeStyle.PerWebRequest) 
      ); 
    } 

지금 말 (인터페이스는 별도의 조립에 그 약 80 종류의) 어셈블리에서 모든 유형을 등록 오버레이를 가져올 때부터 오버라이드 주어진 키에 대해 이미 등록 된 구성 요소가 있습니다 오류가 발생했습니다.

이 등록 후에 라이프 스타일을 수정하는 방법은 여러 가지가 있지만 지금까지는 아무 것도 할 수 없었습니다.

이상적인 해결책은 무엇입니까? 나는 AllTypes 기능을 포기하지 않는 것을 선호합니다. 난 당신이 모든 등록에 대해 얘기하고 생각

답변

1

인가? 그렇다면 수동으로 등록한 구성 요소는 "AllTypes"에 의해 다시 등록되지 않습니다 (클래스를 사용하는 것이 좋습니다). "그룹"등록 후에 수동으로 구성 요소를 등록하는 경우 예외가 발생하지만 반대는 수행되지 않습니다. 예를

//YourImplementation lives in assembly 'a' 
IoC.Container.Register(
    Component.For<YourInterface>().ImplementedBy<YourImplementation>().LifestyleSingleton() 
    ); 

IoC.Container.Register(
    Classes.FromAssemblyNamed(a) 
     .Pick() 
     .WithService.FirstInterface() 
     .Configure(o => o.LifeStyle.PerWebRequest) 
    ); 
+0

이 테스트 것입니다,하지만 그것이 실제로 아주 간단한 해결책 감사 작품 것입니다! –

+0

당신은 환영합니다. 키스 원리 규칙! – Crixo

+0

나는 이것이 작동한다는 것을 확인했다. 내가해야 할 일이 몇 줄이기로 임무를 수행해야한다는 것을 알았던 사람 :] –

3

..

는 내가 모든 등록 어디에요 필터를 지정하고 수동으로 등록 할 수있는 몇 가지 개체를 건너 뛸 수도있을 것 같군요,하지만 아주 진정한 기업용 솔루션 아니다 어셈블리의 일부 유형이 다른 라이프 스타일로 등록되어야하는 어셈블리의 유형 중 하나입니다. 그래서 당신은 PerWebRequest와 ITypeMapper가되어야하는 IRepository를 가지고 있습니다. 이것은 싱글 톤이 될 수 있습니다.

IRepository를 코드의 한 지점에서 PerWebRequest로 지정하고 다른 지점에서 Singleton으로 지정하기를 원하기 때문에이를 분명히합니다. 미친 생활 습관을 만들지 않고도 구성 요소를 만들어 기본 라이프 스타일에 등록 할 수 있습니다. 다른 라이프 스타일이 필요한 경우 가끔 새로운 구성 요소를 만들고 등록 용으로 기존 구성 요소를 상속 할 수 있습니다 (코드 샘플은 혼란 스러울 경우이를 보여줍니다).

샘플을 작성하여 어느 시나리오에서나 작동 할 수 있도록하고 여러 항목을 동시에 구성하는 필터링 기능에 초점을 맞춘 몇 가지 다른 접근법을 제시했습니다.

이 기사에서는 유형별로 특정 구성 요소의 구성을 호출 할 것입니다. 그것은 당신이 그것을 넣는 것처럼 "enerprisey"아니지만, 당신은 규칙에 대한 몇 가지 예외가있는 경우 의도가 명확합니다. 구성을 함께 연결할 수 있습니다. 왜냐하면 두 번째 구성은 첫 번째 구성이 유일한 조건 인 서비스가 IService를 기반으로하기 때문에 구성 요소를 선택하기 때문입니다. 이것은 성이 구성을 순서대로 처리한다고 가정합니다. 나는이 가정이 건전하다고 믿지만 잠시 소스를 보지 않았다.

container.Register(
    Classes.FromThisAssembly() 
     .BasedOn<IService>() 
     .ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton()) 
     .Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0)); 

이것은 하나의 속성을 사용하여 더 일반적으로 일탈 지금 당신에게 (내가 그것을 이해) 할 수 즉각적인 문제를 해결 몇 가지 샘플을 준 것을

container2.Register(
    Classes.FromThisAssembly() 
     .BasedOn<IService>() 
     .ConfigureIf(
      //condition to check - do we have our custom Attribute? 
      registration => registration.Implementation.GetCustomAttributes(false).Any(attr => typeof(ShouldBeSingleton).IsAssignableFrom(attr.GetType())), 
      //if true register as singleton 
      component => component.LifestyleSingleton(), 
      //else register as per web request 
      component => component.LifestylePerWebRequest() 
      )); 

PerWebRequest 정상적인 생활 "에서 내가 당신에게 내 충고를 무료로 해준다!

처음에는 나는 WithService.FirstInterface()를 좋아하지 않는다. 여러 개의 인터페이스를 구현할 때 인텔리 센스 상태가 비결정하다는 것을 알 수있다. 모든 개발자가 들어 와서 무해한 인터페이스 변경을 할 수있다. 클래스와 th에 시스템을 망가뜨려 라. WithService.DefaultInterfaces()로 도망 갈 수 있다면 솔루션을 엉망으로 만들 수 있습니다. 기본 인터페이스는 Foo 구성 요소를 등록 할 때 IFoo라는 인터페이스를 구현하는 경우 서비스 IFoo를 사용한다는 것을성에 알려주는 것입니다.

두 번째로, 등록 논리를 일관된 단위로 분할하면이 문제가 발생하지 않을 것입니다. 핵심은 IWindsorInstaller를 구현하는 많은 설치 프로그램 파일을 갖는 것입니다. 이 인스톨러의 내부에서는 특정 인스톨러에 적합한 유형 (클래스 또는 유형을 사용하여 enterprisey를 계속 유지) 만 등록합니다. 동일한 설치 프로그램에서 여러 가지 라이프 스타일 문제가있는 가능성은 매우 낮습니다. (이 경우 발견하면 더 많은 설치 프로그램이 필요합니다)

이 방법을 사용하면 RepositoryInstaller, ViewInstaller, ControllerInstaller 등으로 끝날 수 있습니다. . More on installers can be found on the castle documentation site

원하는 경우 할 수있는 일은 응용 프로그램 디렉토리를 검색하고 디렉토리에있는 모든 설치 프로그램을 설치하는 모든 시스템에 공통적 인 부스트 래퍼 (boostrapper)를 사용하는 것입니다. 이것이 당신이 요구 한 것이 아니 었습니다. 나는 정교함을 그만 두 겠지만, 관심이 있다면 저에게 핑 소리를 낼 수 있고 제가 말하는 것에 대해 더 많이 보여줄 수 있습니다. 콘솔 응용 프로그램으로

전체 샘플 코드 : 당신이 먼저 수동으로 예외를 등록 할 수있는 옵션

using Castle.MicroKernel.Registration; 
using Castle.Windsor; 
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace MultipleLifecyles 
{ 
    [AttributeUsage(AttributeTargets.Class)] 
    public class ShouldBeSingleton : Attribute 
    { 
    } 

    public interface IService 
    { 
     void DoSomething(); 
    } 

    public class MyComponent : IService 
    { 
     public void DoSomething() 
     { 
      throw new NotImplementedException(); 
     } 
    } 

    [ShouldBeSingleton] 
    public class MyComponentAsSingleton : MyComponent 
    { 

    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 

      //option 1 
      IWindsorContainer container = new WindsorContainer(); 

      container.Register(
       Classes.FromThisAssembly() 
        .BasedOn<IService>() 
        .ConfigureFor<MyComponentAsSingleton>(component => component.LifestyleSingleton()) 
        .Configure(component => component.LifestylePerWebRequest()).Unless(type => container.Kernel.GetAssignableHandlers(type).Count() > 0)); 

      IWindsorContainer container2 = new WindsorContainer(); 

      container2.Register(
       Classes.FromThisAssembly() 
        .BasedOn<IService>() 
        .ConfigureIf(
         //condition to check - do we have our custom Attribute? 
         registration => registration.Implementation.GetCustomAttributes(false).Any(attr => typeof(ShouldBeSingleton).IsAssignableFrom(attr.GetType())), 
         //if true register as singleton 
         component => component.LifestyleSingleton(), 
         //else register as per web request 
         component => component.LifestylePerWebRequest() 
         )); 


      Console.ReadLine(); 
     } 
    } 
} 
+0

를 들어

는 좋은 작성자을 주셔서 감사합니다! +1하지만 다른 답변은 실제로 정확히 내가 뭘 찾고 있었는지 .. 내가 그걸로 문제를 볼 때까지 받아들이는 –