2010-06-25 4 views
6

저는 작업중인 응용 프로그램에서 일관성, 간결함 및 일부 코드의 가독성을 향상시키는 방법을 찾고 있습니다. 시작 코드는 다음과 같습니다.일반 형식 인수가있는 형식의 C# 확장 메서드

context.GetGraphType<Bar>().Subscribe<Fizz>(
    (instance, evt) => e.Execute((Bar)instance.Instance) 
); 

위와 같이 거의 동일한 코드 행이 있습니다.

typeof(Bar).SubscribeTo<Fizz>(context); 

우선,이 날 이미 비공식적 인 규칙이되었다 무엇을 공식화을 활용할 수있는 것 :이 같은 것을보고 그것을 다시하고 싶었다. 또한, "컨텍스트가 막대 유형을 얻고 fizz에 가입 한 다음 몇 가지 작업을 수행합니다."보다는 "주어진 컨텍스트에서 fizz 이벤트를 구독합니다"와 같은 내용을 읽을 수 있기를 기대했습니다. 더 나은, 그리고 내가 그것에 대해 물어 동료가 동의했다.

이 방법을 확장 메소드로 구현하기 시작했습니다. 위의 작업을 수행하기 위해 이벤트 유형에 대한 추상적 제네릭 기본 클래스를 사용하고자 했으므로 FizzEvent<T>이됩니다. 이것은 확장 메서드에 대한 제네릭 형식 인수가 확장 메서드가 호출되는 형식이되도록 제한되어야 함을 의미합니다. 따라서 위 예의 경우 FizzEvent<Bar>이어야합니다.

이것이 가능합니까? 나는 대체 시간의 해결책으로 갔다. 그러나 그것이 성취 될 수 있다면 나는 여전히 궁금하다. 다른 제안도 환영합니다.

감사합니다.

편집 # 1 : 분명히 알 수 있듯이 추가 유형 매개 변수를 사용할 수 있다는 것을 알고 있지만 가능한 경우이를 피할 수있는 방법을 찾고 있습니다.

편집 # 2 : 내가 시나리오와 100 % 일치하지 않기 때문에 받아 들여진 답변의 약간의 변형과 함께 갈 것입니다. 결론은 Type의 확장 메서드 대신 일반 정적 클래스를 사용하여 목표를 달성 할 수 있다는 것입니다. 감사합니다 dss539!

public class Bar { } 

public class Event<TSubscriber> 
{ 
    public abstract void Execute(TSubscriber source); 
} 

public class Fizz : Event<Bar> 
{ 
    public override void Execute(Bar bar) 
    { 
     // respond to event 
    } 
} 

public class Context { } 

public static class ForType<TSubscriber> 
{ 
    public static void SubscribeTo<TEvent>(Context context) 
     where TEvent : Event<TSubscriber> 
    { 
     context.GetType<TSubscriber>().Subscribe<TEvent>(
      (evt, args) => evt.Execute((TSubscriber)args.Source)); 
    } 
} 

public static void Run() 
{ 
    ForType<Bar>.SubscribeTo<Fizz>(context); 
} 
+1

나는 당신의 질문을 이해하지 못합니다. 기존 메서드 서명은 어떤 모양입니까? '구독 (이 유형 유형, 조치 )'? 자신이 가지고있는 것을 보여 주면 (또는 동등한) 설명이 도움이 될 수 있습니다. – dss539

+0

나는 비슷한 디자인 문제를 가지고 있다고 생각한다. 행운을 빌어 요. – leppie

+0

@ dss539 (이 유형 유형, 컨텍스트 ctx)과 같을 것입니다. 문제는 T가 타입 이벤트 유형의 "유형"매개 변수가되도록 제약하는 방법이 없다는 것입니다. –

답변

6

이것은 당신이 물었다하지만 어쩌면 그것은 충분 똑같이하지 않습니다.

internal class Program 
{ 
    static void Main(string[] args) 
    { 
     var fizzHandler = new Fizz(); 
     var context = new Context(); 
     Handle<Bar>.With(fizzHandler, context); 
    } 
} 
public class Bar { } 
public class Event<T> { } 
public class Fizz : Event<Bar> { } 
public class Context { }; 
public static class Handle<T> 
{ 
    public static void With(Event<T> e, Context c) 
    { 
     //do your stuff 
    } 
} 
+0

이것은 정확히 내가 찾고있는 것입니다. 컴파일러를 우회하지 않고 원래의 가독성 목표를 달성 할 수 있습니다. 감사! –

+0

@ 브라이언 - 내가 도울 수있어서 다행 :) – dss539

4

당신이 규칙을 적용하는 일반적인 제약 조건을 사용할 수있는 좀 더 숙어 무언가를하지 왜 :

업데이트 코드 (나는 즉시이 일을 해요 때문에 오타가있을 수 있습니다)

public static class SubscriptionManager 
{ 
    public static void SubsribeTo<TSub,TEvent>(Context context) 
     where TEvent : Event<TSub> 
    { 
     /// you code... 
    } 
} 

호출과 같을 것이다 :

SubscriptionManager.SubsribeTo<Bar,Fizz>(context); 

제약 where TEvent : Event<TSub>은 원하는 이벤트 유형과 구독 유형 간의 관계를 보장합니다. 그것은 또한 나의 책에서 클래스 Type에 대한 확장 메소드에 선호합니다 - 왜냐하면 그것은 intellisense를 혼란스럽게하는 경향이 있기 때문입니다. Type은 많은 경우에 사용되며 모든 경우에 Intellisense에 나타나는 가짜 방법을 사용하면 Type이 혼란 스럽습니다. 또한 도서관 이용자가 실제로 코드 예제를 본 적이없는 한 "구독"하는 방법이라는 것이 명백합니다.

+0

답변 해 주셔서 감사합니다! 제약이 이러한 방식으로 시행 될 수 있다는 것을 알았습니다 (위의 편집 참조). 귀하의 제안은 내가 고려한 것에 가깝지만 확장 방법을 선호했습니다. Type과 같은 클래스에서 확장 메서드를 사용하는 것을 싫어하지만이 메서드는 구독을 처리하는 단일 클래스로 지역화되어 있습니다. 또한, 다른 사람들이 소비하게 될 도서관 방법이 아닙니다. –

0

System.Type (typeof(T).)으로 확장하고 .NET 형식을 내부 형식 표현 (GetGraphType에서 반환 된 것과 동일)으로 변환하는 컨텍스트에 (확장) 메서드를 추가 할 수 있습니다.

static class Ext { 

    public static TypeofTypeofBar GetGraphTypeFromDotNetType(this Context ctx, Type t) { 
     return __something(t); 
    } 

    public static void SubscribeTo<F, E>(this Type type, Context ctx, E e) 
     where E: Event<T> { 
     context.GetGraphTypeFromDotNetType(type).Subscribe<F>(a); 
    } 

} 

...

typeof(Bar).SubscribeTo(context, action); 
+0

안녕하세요, Mau입니다. 이미 설명한 방법이 이미 존재합니다. 귀하의 예제에서 형식 매개 변수에 대해 약간 혼란 스럽습니다. "E : Event "을 의미 했습니까? 그럴 경우 "이벤트"인수를 전달할 필요가 없으며 실제로 이벤트 인스턴스를 제공 할 수 없습니다. 그러나 가입자의 유형이 여전히 유형 매개 변수로 제공되어야하는 것처럼 보입니다. 그래서, 기본적으로 "typeof (Bar) .SubscribeTo (ctx)"로 끝날 것입니다. 이것은 내가별로 흥분하지 않은 또 다른 변형입니다. 그래도 제안에 감사드립니다! –