2009-09-01 3 views
4

나는 내가 dodgey 조금있을 수 있습니다 의심되는 코드에서 다음과 같은 상황이 :는 C#에서 일반 클래스에 정적 메서드에 액세스

I 클래스가 있습니다

abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass 

는이 클래스 DataAccessBase도있다을 이제

static IDataAccess CreateInstance(TypeToCreateEnum) 

의 타이하십시오있는 문에서 열거 값을 사용하여 자체의 파생 클래스의 인스턴스를 생성하는 정적 팩토리 메소드는 생성하는 유형을 도출 결정합니다 이 제네릭을 잘 사용의 한계를 밀어 경우

class PoLcZoneData : DataAccessBase<PoLcZone> // PoLcZone is derived from AnotherAbstractClass 

지금까지 내가 잘 모르겠지만, 나는 어떻게 정말 걱정 무엇 이니 DataAccessBase<T>에서 파생 된 PES 자신에게 일반적인하지, 그들은 T에 대한 유형을 지정 처음에 정적 CreateInstance() 메서드에 액세스하려면 다음을 수행하십시오.

현재이 작업을 수행하는 방법은 T : AnotherAbstractClass 인 모든 유형 T를 전달하는 것입니다. 특히 나는 AnotherAbstractClass 그 자체를 전달하고있다. 이것은 컴파일을 잘 해주지 만, 모든 타입을 일반 클래스로 전달하는 것만으로도 통계학에서 얻는 것이 약간 교묘합니다.

실제로는 DataAccessBase<T>이 상속 체인의 하위 레벨이기 때문에 상황을 다소 간소화했지만 static 팩토리 메소드는 중간이 아니며 일반적인 레벨이 아닌 유일한 레벨에서 PoLcZoneData과 같은 클래스가있는 클래스가 있습니다.

이 약정에 대한 사람들의 생각은 무엇입니까?

+0

이 어떤 언어입니다

디미트리? –

+0

죄송합니다. C#입니다. 제목에 추가하는 것을 잊어 버렸습니다. – MrLane

답변

9

당신은 아마 뭔가처럼 ... 같은 이름의 제네릭이 아닌 클래스를 가질 수 있습니다. 일반적으로 DataAccessBase<T>에서 internal 메서드를 호출 할 수 있습니다. DataAccessBase - 시나리오에 약간의 반사가 필요하다고 판단 되더라도/MakeGenericType.

0

특별히 디자인 매개 변수를 사용하여 구현 세부 사항을 지정하는 경우 해당 디자인에 문제가 있다고 생각하지 않습니다. 내가 제안하는 것은 단순히 공장 기능을 정적이 아닌 단순한 스탠드로 유지하는 것입니다. 그것은 나를 위해 그것에 대해 갈 가장 clearcut 방법이 될 것입니다.

어떤 방식으로 캡슐화하려면 네임 스페이스 또는 명명 규칙을 제안해야합니다.

는 또 다른 해결책은 어쩌면과 같이 DataAccessBase의 유형을 정의하여, 현재 무엇을하고 있는지 숨어있을 것이다 : 이것은 내 최소 권장 솔루션

typedef DataAccessBase<AnotherAbstractClass> DataAccessBaseFactory; 

이지만 정적으로 생성 기능을 잎 당신이 절대적으로 원한다면.

abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass 
{ 
    ... 
} 
static class DataAccessBase 
{ 
    public static IDataAccess CreateInstance(TypeToCreateEnum) {...} 
} 

지금 당신이 어떤 중복 T없이 DataAccessBase.CreateInstance를 사용할 수 있습니다

+0

@killerfox 이것은 C# –

+0

입니다.이 경우에는 네임 스페이스가 아닌 별도의 클래스에 팩토리 함수를 캡슐화하는 것이 유일한 옵션이라고 생각합니다 –

2

얼마 전에 비슷한 문제가 발생했습니다 ("정적 메서드를 오버로드하는 방법"). 그리고이를 Reflection으로 해결했습니다.내가 예를 들어, 일부 정적 방법을 정의

1) public abstract class AuditObject<T> : ActiveRecordBase<T> (예 내가 사용 액티브)과

2) 둘 다에서 public class Employee : AuditObject<Employee>

: 여기

내 상황입니다 내가 예를 들어, 호출 할 때

public static DataTable GetLookupTable(String where, Int32 topRows) 
{ 
    return doExtremelyCleverStuffToFetchData(where, topRows); 
} 

코드이기 때문에

(# 2에서 당신은 컴파일러 경고를 public **new** static이 필요하거나 다른)

DataTable myList = AuditObject<T>.GetLookupTable("inactive = 0", 100); 

... T 및 종업원 인이 정적 메소드가 아닌 "재정의", 즉 실행되는 하나의 방법 (1)하지 (2).

(1) 나는이 같은 (예, GetLookupTable의) 정적 방법을 수정 그래서에서 :

여기
public static DataTable GetLookupTable(String where, Int32 topRows) 
{ 
    DataTable tbl = null; 

    Boolean hasOverride = hasMethodOverride("GetLookupTable"); 

    if (hasOverride) 
    { 
     tbl = invokeStaticMethod<T>(
      "GetLookupTable", new Object[2] { where, topRows }) 
      as DataTable; 
    } 
    else 
    { 
     tbl = doExtremelyCleverStuffToFetchData(where, topRows); 
    } 

    return tbl; 
} 

의 정적 메소드가있는 경우 내가 알아 방법 :

private static Boolean hasMethodOverride(String methodName) 
{ 
    var methodQuery = 
     from method in typeof(T).GetMethods(
      BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod) 
     where method.Name == methodName 
     select method; 

    return methodQuery.Count() > 0; 
} 

을 그리고 '재정의'메소드가 호출되는 방법은 다음과 같습니다.

public static Object invokeStaticMethod<T>(String MethodName, Object[] Args) 
{ 
    return typeof(T).InvokeMember(MethodName, 
     BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, 
     null, null, Args); 
} 

Voila! DataTable myList = AuditObject<T>.GetLookupTable("inactive = 0", 100); 을 호출하고 T가 Employee 인 경우 Employee 클래스에 정의 된 정적 메서드의 결과를 얻습니다. 이 도움이

희망,

관련 문제