2010-06-03 2 views
2

Я пытаюсь хранить типы в коллекции, так что я могу позже создавать объекты типов в коллекции. Но я не уверен, как это сделать наилучшим образом.возможно ли это: C# коллекция типа с ограничениями или коллекция общего типа?

Что я до сих пор:

List<Type> list = new List<Type>(); 
list.Add(typeof(MyClass)); 
var obj = (MyClass)Activator.CreateInstance(list[0]); 

Я хотел бы иметь некоторые ограничения целостности на Type, или еще лучше, просто общий вид в коллекции вместо реализованного Type объекта. Это возможно?

ответ

3

В данном конкретном случае, где, кажется, у нас есть «фабрика» образец, мы бы ограничить метод, вызывающий активатор, такие как

private readonly List<Type> _supportedTypes = new List<Type>(); 
public void RegisterSupportedType<T>() where T : SomeConstraintType 
{ 
    _supportedTypes.Add (typeof (T)); 
} 

// if we do not know the type, but somehow know an index to type 
public object Create (int supportedTypeIndex) 
{ 
    object untyped = Activator. 
     CreateInstance (_supportedTypes[supportedTypeIndex]); 
    return untyped; 
} 

// if we know instance type\subtype (eg interface) and know an index 
public T Create<T> (int supportedTypeIndex) 
{ 
    T typed = default (T); 
    object untyped = Create (supportedTypeIndex); 
    if (!(untyped is T)) 
    { 
     // throw meaningful exception :) 
    } 
    typed = (T)(untyped); 
    return typed; 
} 

Альтернативы, является создание ограниченного Type

public class ConstrainedType<T> 
{ 
    public Type Type { get; private set; } 
    public ConstrainedType (Type type) 
    { 
     // may have this backward, would have to fact check before 
     // rolling out to prod ;) 
     if (!typeof (T).IsAssignableFrom (type)) 
     { 
      // throw meaningful exception! 
     } 
     Type = type; 
    } 
} 

List<ConstrainedType<SomeTypeConstraint>> list = 
    new List<ConstrainedType<SomeTypeConstraint>>(); 

// will throw meaningful exception if MyClass is not 
// SomeTypeConstraint or a sub class 
list.Add (new ConstrainedType (typeof (MyClass))); 

SomeTypeConstraint baseType = 
    (SomeTypeConstraint)(Activator.CreateInstance(list[0].Type)); 
+0

Спасибо! Я думаю, что фабричная модель может работать. –

+0

@ Jon, как fyi, вы также можете исследовать инверсию управления [IoC] и инжекцию зависимостей [DI]. причудливые имена для относительно простых понятий, и уже существует несколько «зрелых» фреймворков, которые реализуют обобщенные заводские шаблоны, как описано выше. например, Unity 2.0 MS, а также Castle Castle Windsor Container. –

+0

Большое спасибо! Оказывается, единство было именно тем, что мне нужно. Я использую его для регистрации типов и для создания новых объектов, отслеживая зарегистрированные типы в списке. Отлично! –

0

Первый способ (кажется глупым, но безопасным):
(создайте оболочку над List || реализуйте IList) и проверьте .Exists (item) в .Add Method.

0

Если вы должны были реализовать свою собственную коллекцию, вы можете использовать общие ограничения типа:

public class MyList<T> 
    where T : IMyConstraint 
5

Это не то, как работают общие ограничения сбора.

Generic constraints ограничить, какие типы являются законными для создания экземпляра родового типа. Существует несколько различных ограничений, но общие ограничивают общий параметр либо наследовать, либо быть экземпляром данного типа, либо быть типом, реализующим конкретный интерфейс (или набор интерфейсов).

Type, с другой стороны, является классом, который описывает информацию о типе в приложении или в одной из его библиотек. Конкретные виды типов не наследуют или не расширяются Type - скорее, существует отдельный экземпляр из Type для каждого типа. Вы не можете использовать общие ограничения для контроля того, какие экземпляры Type могут быть добавлены в вашу коллекцию.

Без дополнительной информации о том, как вы хотите «ограничить» информацию в коллекции, трудно сказать, какой маршрут вы должны предпринять. Например, если все, что вы хотите сделать, это убедиться, что хранятся только уникальные типы (без дубликатов), которые могут быть достигнуты с помощью HashSet (а не списка). Но если вам нужно что-то более специализированное - например, ограничение экземпляров Type, которые могут быть добавлены к некоторому подмножеству типов, тогда вам, скорее всего, понадобится реализовать свою собственную коллекцию и реализовать логику gaurd в методах «Добавить/Вставить».

+0

Спасибо! На самом деле я хочу делать как то, так и без дубликатов и только типы, которые наследуются от определенного базового класса. Я думаю, что заводская модель johnny g, представленная ниже, будет соответствовать моим потребностям. –

1

Джон,

Если вы используете CodeContracts, то может потребоваться несколько известных типов. Анализ кода будет отмечать любые вызовы вашей коллекции с недопустимыми типами.

public class TypeCollection : List<Type> 
{ 
    public TypeCollection() 
    { 
    } 

    public new void Add(Type type) 
    { 
     Contract.Requires(type == typeof(string) || type == typeof(Stream)); 
     base.Add(type); 
    } 
} 

public class TestCollection 
{ 
    public void Test() 
    { 
     TypeCollection collection = new TypeCollection(); 
     // This gets compile time warning: 
     collection.Add(typeof(int)); 
    } 
} 

Но, если вы знаете тип заранее, это могло бы иметь больше смысла, чтобы указать их все в перечислении и создать коллекцию действительных перечислений для создания типа вы хотите поддержать.

+0

Я не использую CodeContracts, может быть, должен. На данный момент, я думаю, что заводская модель johnny размещена будет surfice –

Смежные вопросы