2016-06-15 4 views
1

일부 데이터 원본에서 데이터 가져 오기 및 게시를 일반화하는 클래스 시스템을 만들려고합니다. 두 가지 방법이 있습니다 : GetData 및 PostData. 두 메서드 모두 어떤 종류의 입력이 있어야하며 GetData도 반환 형식이어야합니다. 일반 인터페이스 구현 : 일반 반환 형식 및 일반 입력 형식

public class QueryParameter 
{ 
    public QueryParameter() 
    { 
     this.Direction = ParameterDirection.Input; 
    } 

    public string Name { get; set; } 
    public object Value { get; set; } 
    public ParameterDirection Direction { get; set; } 
} 

public class InputBase 
{ 
    public InputBase() 
    { 
     ResultMapping = new Dictionary<string, string>(); 
     Parameters = new List<QueryParameter>(); 
    } 
    public Dictionary<string, string> ResultMapping { get; set; } 
    public List<QueryParameter> Parameters { get; set; } 
} 
public class DatabaseInput: InputBase 
    { 
     public string Query { get; set; } 
     public DatabaseCommandType CommandType { get; set; } 
    } 

public interface IDataSource<I> where I: InputBase 
{ 
    IEnumerable<T> GetData<T>(I input); 
    void PostData(I Input); 
} 

지금 내가이 같은 인터페이스를 구현하려고 : 나는 일반적인 인터페이스를 작성하고 "DatabaseSource"클래스에서 구현하려고

public class DatabaseDataSource: IDataSource<DatabaseInput> 
{ 
    public IEnumerable<T> GetData<T>(DatabaseInput Input) 
    { 
     //implementation 
    } 

    public void PostData(DatabaseInput Input) 
    { 
     //implementation 
    } 
} 

하지만 데이터를 인스턴스화 할 때 나는 문제가 이 같은 소스 :

IDataSource<InputBase> dataSource = new DatabaseDataSource(); 

이 코드는 팩토리 메소드의 어떤 종류의 내가 다른 인 IDataSource 구현을 인스턴스화 할 수 있어야하기 때문에이 DatabaseInput을 사용할 수 없습니다.

요약하면 입력 및 출력을 제네릭 형식으로하고 Constraint Input이 콘크리트 IDataSource 구현과 일치하도록하고 싶습니다.

+0

당신은 where 연산자를 통해 이것을 할 수 있습니다. http://stackoverflow.com/questions/1096568/how-can-i-use-interface-as-ac-sharp-generic-type-constraint –

+0

where 연산자를 사용하여 시도했습니다. ,하지만 여전히 내 질문에 마지막 코드 섹션에서처럼 인스턴스 수 없습니다 – vpetrovic

+0

'DatabaseDataSource'는'IDataSource '이 아닌'IDataSource '입니다. 구체적인 유형의 공분산은 할 수 없습니다. 참조 : https://msdn.microsoft.com/en-gb/library/dd799517(v=vs.110).aspx – TheInnerLight

답변

0

제약 조건에 대한 자세한 내용은 where 제약 조건을 사용하고 here을 클릭하십시오.

where T : class //The type argument must be a reference type; this applies also to any class, interface, delegate, or array type. 

where T : <interface name> //The type argument must be or implement the specified interface. Multiple interface constraints can be specified. The constraining interface can also be generic. 
+0

그는이 문제를 이미 시도하고 있습니다. 그 의미는 잘못되었습니다. –

+0

제약 조건은 어디까지인지 알고 있지만 빌드 할 수는 없습니다. 나는 이것에 대한 구체적인 예가 필요하다. 내 질문에 나의 문제를 기술했으면하고, 알다시피, 나는 '어디서'의 정의를 사용하려고했는지 알기를 바란다. – vpetrovic

3

정확하게 이해하고 있으면 100 % 명확하지 않습니다. 데이터 소스는 입력 을 모두 정의해야합니다. 이렇게하면 :

public IEnumerable<T> GetData<T>(DatabaseInput Input) 

그런 다음 그 방법의 실제 구현은 T이 무엇인지에 따라 크게 달라질 수 있습니다. T 유형을 검사하고 그에 따라 코드를 분기하는 시나리오의 시나리오는 원하지 않습니다.

아마도 당신이 원하는 것은이 같은 것입니다 :

public interface IDataSource<TInput, TOutput> where TInput: InputBase 
{ 
    IEnumerable<TOutput> GetData(TOutput input); 
    void PostData(TInput Input); 
} 

하지만 그렇다하더라도 당신은 겉보기에는 아무 연관없는 두 가지 작업을 정의하는 것 인터페이스를 가지고있다. (. 그것은 TInput 데이터를/게시 수정하는 데이터를 검색하는 쿼리로하고 명령으로 사용할 수 있습니다 같지는 않다)

을 그래서 아마 당신은 그것을 더 고장날 수 :

public interface IDataSource<TInput, TOutput> where TInput: InputBase 
{ 
    IEnumerable<TOutput> GetData(TOutput input); 
} 

public interface IDataCommand<TInput> where TInput:InputBase 
{ 
    void PostData(TInput Input); 
} 

가 인스턴스화하기 당신은 추상 팩토리를 사용할 수 있습니다 : 그것은 당신의 클래스가 var dataSource = new [whatever].를 호출 할 필요성을 피할 수 있기 때문에

public interface IDataSourceFactory<TInput, TOutput> 
{ 
    IDataSource<TInput, TOutput> Create(); 
    void Release(IDataSource<TInput, TOutput> created); 
} 

그 이유는 당신이 그 때 다소 인터페이스를 구현의 목적을 패배 그렇게한다면. new을 명시 적으로 호출하고 특정 유형을 만들 자마자 구현하는 인터페이스에 관계없이 클래스는 인터페이스가 아닌 유형 인 에 결합됩니다.

원래 문제가 이동합니다. 추상 팩토리의 구현은 무엇입니까? 좋은 소식은 공장에 의존하는 클래스는 공장의 구현이 무엇인지 신경 쓰지 않는다는 것입니다. 그러나 당신은 여전히 ​​그것을 필요로 할 것입니다.그것에 대해 갈 수있는 한 가지 방법은 DI 컨테이너를 사용하는 것입니다. Windsor는 추상 팩터 리 생성 패턴을 제공하므로 유용합니다. This blog post에 자세히 설명되어 있습니다.

+0

스콧, 나는 당신의 대답을 더 자세하게 읽을 것이다. InputBase가 무엇인지 명확히하고 싶습니다. GetData의 경우 데이터 필터링에 사용되는 매개 변수를 제공하는 기본 클래스이거나 PostData의 경우 일부 업데이트 쿼리의 매개 변수입니다. 그리고 TResult에 관해서는 TResult 객체에서 리플렉션을 사용하여 데이터를로드하려고합니다. – vpetrovic

+0

그건 내가 생각한거야. 'public interface IDataSource where I : InputBase'를 선언하고 그 메소드가 "get"과 "post"둘 다 선언하고 둘 다 매개 변수로'I'를 취하면 그 값은 정확히 같은'I' (구현 'InputBase')는 질의 파라미터와 업데이트/삽입/삭제 파라미터로 모두 사용할 수 있어야합니다. 그러나 실제로는 쿼리 매개 변수가 달라집니다. 예를 들어 엔터티에 날짜가 있으면 쿼리에 시작 및 종료 날짜 매개 변수가 포함될 수 있지만 삽입 또는 업데이트 명령에는 쿼리 범위가 아닌 실제 날짜가 포함됩니다. –