"무엇이든"일반적인 컬렉션을 반환하는 방법을 선언하는 방법 (C#)
-
12-09-2019 - |
문제
나는 추상적 인 기본 클래스에서 파생되는 일반 컬렉션 클래스의 계층 구조를 사용하여 추상 기본 클래스에서 파생되는 엔티티 항목을 저장합니다.
abstract class ItemBase { }
class MyItem : ItemBase
{
public MyItem()
{
}
}
abstract class CollectionBase<T> : Collection<T> where T : ItemBase, new() { }
class MyCollection : CollectionBase<MyItem> { }
이 모델의 목표는 CollectionBase에서 파생 된 모든 클래스의 구성원에 대한 엄격한 유형의 징계를 시행하는 것입니다.u003CT> 이 회원들에게는 기본 공개 생성자가 있음을 보장합니다. 지금까지 그것은 작동합니다.
이제 CollectionBase에서 파생 된 클래스 인스턴스를 반환하는 공장 메소드를 만들고 싶습니다.u003CT> . 일반적인 접근 방식은 다음과 같습니다.
public CollectionBase<T> CreateCollection<T>();
... 또는 어쩌면 ...
public T Create CreateCollection<T>();
그러나 문제는 호출 루틴이 "T"가 필요한 것을 알지 못한다는 것입니다. 반품 할 특정 유형의 컬렉션을 결정 해야하는 것은 공장 방법 자체입니다. 따라서 "리턴 유형은 CollectionBase에서 파생된다고 말하는 비 게 릭 메소드 서명이 필요합니다.u003CT> ". 나는 이와 같은 것을 상상합니다 (합법적 인 경우) ...
public CollectionBase<> CreateCollection();
나는 이것이 가시적 인 일반적인 분산 문제 중 하나라고 생각하지만, 주제에 대한 에릭 립퍼트의 광범위한 설명을 읽은 후에도 C# 4.0에서 내가하려고하는 것이 실현 가능하고 단순한 것이 있는지 여부는 여전히 불분명합니다. C# 3.0의 해결 방법.
당신의 아이디어에 미리 감사드립니다.
해결책
공장 방법이 단일 항목을 생성한다고 가정 해 봅시다. 너도 아마:
public ItemBase CreateItem();
당신은 사용해야합니다 ItemBase
더 구체적인 것을 알 수 없기 때문입니다. 해당 원리를 수집 방법에 적용하면 다음을 얻을 수 있습니다.
public CollectionBase<ItemBase> CreateCollection();
분산 부족으로 인해 발생하는 어댑터 클래스가 필요합니다. CollectionBase<ItemBase>
생성 된 실제 컬렉션을 랩핑합니다.
C# 4.0에서는 실제 컬렉션을 반환합니다.
편집하다: 공장은 어댑터가 포함 된 상태에서 다음과 같이 보일 수 있습니다.
public class CollectionFactory
{
public CollectionBase<ItemBase> CreateCollection()
{
if(someCondition)
{
return CreateAdapter(new MyCollection());
}
else
{
return CreateAdapter(new MyOtherCollection());
}
}
private static CollectionAdapter<T> CreateAdapter<T>(CollectionBase<T> collection) where T : ItemBase, new()
{
return new CollectionAdapter<T>(collection);
}
private class CollectionAdapter<T> : CollectionBase<ItemBase> where T : ItemBase, new()
{
private CollectionBase<T> _collection;
internal CollectionAdapter(CollectionBase<T> collection)
{
_collection = collection;
}
// Implement CollectionBase API by passing through to _collection
}
}
다른 팁
아마도 당신이 필요로하는 것은 다음과 같습니다.
public CollectionBase<Object> CreateCollection();
모든 클래스가 직간접 적으로 객체 클래스에서 상속되기 때문입니다.
나는 실제로 이것을하지 않았고 그것이 완전히 순진하지만 ...
public CollectionBase<Object> CreateCollection();
?
당신이 정말로 그것이 무엇이든 원한다면, 당신은 단지 iCollection을 반환 할 수 있고, 당신의 소비자는 .Cast<ItemBase>()
필요에 따라 확장 방법.
내가 이해 한 바에 따르면 .NET 4.0에서는 반환 할 수 있습니다. CollectionBase<ItemBase>
, 그러나 나는 아직 베타에서 시도하지 않았습니다.