2012-02-21 6 views
1

내 설계가 잘못되어 내 문제를 해결하는 방법을 묻습니다. 팩토리 메서드의 생성자에 대한 제약 조건 유형

그래서 내 경우 : 나는 클래스 공장 방법을 쓰고 있어요

는, 마녀는 나의 특별한 기본 클래스에서 파생되었다. 그래서 내가 썼다

public T MyFactory<T>() where T:MyBaseClass 

그러나 내 공장 방법의 주요 작품은 몇 가지 특별한 매개 변수를 받고 새로운 개체의 생성자로 전달하고있다. MyBaseClass이 생성자가 있습니다

public MyBaseClass(MySpecParam param){...} 

을하지만이 MyBaseClass에서 파생 된 T을 입력 보장은 없다 같은 생성자를 가지고있다.

내가 볼 수있는 유일한 솔루션은 공장 안전하게 유형 T의 새로운 객체를 만든 다음 MySpecParam 객체로 init을 할 수 있도록, MyBaseClassnew() 제약 및 가상 Init 방법을 추가하는 것입니다.

그러나 은 그러한 디자인이므로, MySpecParam으로 의견을 제시하지 않으면 완전히 사용할 수 없습니다. 그리고 사용자는 매개 변수없는 생성자를 사용하여 MyBaseClass을 생성하고 초기화되지 않은 객체를 완전히 무효화 할 수 있습니다. 나는 그것이 좋지 않다고 생각한다.

new(MySpecParam) 제약을 추가 할 방법이 없습니다.

개체, 생성자 및 팩토리 메서드를 어떻게 디자인해야합니까?

+0

인터페이스 할 수 없습니다 containts 생성자 – Yavanosta

답변

2

각 클래스는 하나의 공용 생성자가있는 경우, 당신은 반사에 의해, 그것은 무엇이 매개 변수를 결정하고 (반사를 통해 계속) 생성자를 호출 할 때 적절한 값을 제공 할 것을 찾을 수 있습니다.

그렇지 않으면 유한 생성자 서명이 있다고 가정합니다. 이 경우 호출 할 생성자를 결정하는 방법이 필요합니다. 결정은 부분 인수 T의 ID에 부분적으로 기초 할 수 있습니다. 당신이 당신의 의견에 설명 된 이유에 대한 반사를 사용하고자하지 않은 경우

편집

는, 그 대답은 다소 "아니, 당신은 할 수 없어"입니다. Michael Yoon은 IoC 프레임 워크를 제안합니다. 물론 IoC 프레임 워크는 리플렉션을 사용하며 런타임 오류가 발생할 수 있습니다. Castle Windsor에서의 경험에 비추어 볼 때, 성능은 결코 문제가 아니며 잘못 구성된 결과로 발생하는 런타임 오류는 개발 사이클에서 거의 즉시 발견됩니다.

또 다른 생각; 이것은 도움이되지 않을 수도 있지만 고려 가치가있을 수 있습니다. 당신은 또한

var obj = FactoryMethod<SomeType>(() => new SomeType(23)); 

전화 Func<T, TOut>의 다른 유형, Func<T1, T2, TOut>, 등의 팩토리 메소드의 오버로드에도 인스턴스를 생성하기 위해 Func<T>를 사용하거나 할 수는 abstract factory pattern을 고려하십시오.

+0

이 나쁜 곳이이 방법이 있습니다 : 1. 반사가 정말 expencive와 느린 2.이 될 것입니다 생성자 잘못된 클래스 또는 공장 프로그래머 사용 공장 수없는 선택하는 경우 런타임 오류가 발생하지만 컴파일 타임에 유형 안전성을 제어하는 ​​것이 훨씬 더 좋습니다. – Yavanosta

+0

@ Yavanosta 성능 측면에서 반사의 나쁜 점은 프레임 워크의 이전 버전에서 비롯된 것입니다. 최신 버전에서는 다소 최적화되었습니다. 아직도, 그것은 더 느립니다. 그리고 물론 컴파일 타임 검사를하는 것이 좋을 것입니다. 그러나 매개 변수화 된 생성자가 필요하다면 도움이되지 않는 'new()'제약 조건을 사용하는 것이 유일한 방법입니다. 더 많은 생각을 보려면 편집 된 답변을 참조하십시오. – phoog

+0

@Yavanosta 나는 더 많은 아이디어를 가지고 다시 편집했다. – phoog

2

소리가 IoC 컨테이너의 문제와 유사합니다. 팩토리에서 StructureMap 또는 Unity와 같은 컨테이너를 사용했다면 생성자 문제는 더 이상 걱정할 필요가 없습니다.팩토리는 MyBaseClass를 해결하기 위해 StructureMap (예를 들어)을 요청할 것이고, greediest 생성자를 사용하여 MyBaseClass 인스턴스를 리턴하고 모든 의존성을 재귀 적으로 빌드하는 등의 작업을 수행합니다.

1

생성자가 상속되거나 인터페이스에 허용되지 않습니다. 즉, 각 클래스의 생성자는 해당 클래스에만 고유합니다. 즉, 패턴과 일치하는 생성자가없는 기본 클래스로 하위 클래스를 만들 수 있습니다. 객체를 구성하는 표준 방법을 원한다면 기본 클래스에서 생각과 비슷한 abstract Init(foo, bar, baz)이 가장 좋은 해결책이라고 생각합니다. 개체가 초기화되기 전에 액세스되는 경우 throw되는 내부 논리를 구현할 수도 있지만 불행히도 컴파일 타임에 해당 개체를 적용 할 수는 없습니다.

관련 문제