Непатентованный вопрос в C # - PullRequest
1 голос
/ 04 июля 2011

Я пытаюсь реализовать таблицу, разделив ее на 3 уровня.

class Field -> 
      class Record (witch holds a collection of fields ) -> 
              class Table(witch holds a collection of Records)

Теперь мой вопрос не о том, как правильно структурировать эту реализацию, хотя любые указатели приветствуются.

У меня возникла проблема с реализацией универсального класса поля

 public class Field<T>
 {
     T value; 
     Type _type; 
     string _header;
 }

Я не знаю, какого типа T будет, поэтому мне нужно определить класс с помощью, теперь проблема, с которой я сталкиваюсь, состоит в том, что коллекция Field в классе Record, скорее всего, будет содержать различные типы T , и это своего рода побеждает все цели

public class Record
{
   List<Field<object>> fields ;        
}

так что теперь мне нужно привести T к объекту, потому что T не будет определенного типа.

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

плюс любые указания о моей идее реализации

мой стол состоит из

    class Table  
    {   
          KeyValuePair<string,Type>[] columns ;
          KeyValuePair<string, Type> primary_key;
          string entitie_name ; 
          List<Reocrd> records ;
    }
    // the Record class could be created only from a table template just like a datarow
    public class Record
    {
          List<Field<object>> fields ;
          string primary_key ;// the name of the field witch i use to extract a value              
    }

10x заранее.

Ответы [ 2 ]

2 голосов
/ 04 июля 2011

Шаблон, который вы обычно можете найти в .NET Framework, - это определение неуниверсального базового класса или интерфейса:

public abstract class Field
{
    protected Field() { }

    public abstract BoxedValue { get; set; }

    public abstract Type ValueType { get; }
}

public class Field<T> : Field
{
    private T value; 

    public Field(T value) { this.value = value; }

    public T Value
    {
        get { return this.value; }
        set { this.value = value;; }
    }

    public override object BoxedValue
    {
        get { return this.value; }
        set { this.value = (T)value; }
    }

    public override Type ValueType
    {
        get { return typeof(T); }
    }
}

Класс Record предоставляет коллекцию неуниверсальных полей:

public class Record
{
    public IEnumerable<Field> Fields { get { ... } }
}

Если код должен получить значение полей без упаковки, ему необходимо сначала привести экземпляр поля к соответствующему полю .

Пример:

foreach (Field<int> field in record.Fields.OfType<Field<int>>())
{
    int value = field.Value;
    Console.WriteLine(value);
}
0 голосов
/ 04 июля 2011

Я склонен использовать здесь интерфейсы

IField ... создать универсальный класс, который использует этот

Затем наследовать это с

Интерфейсом IField

теперь у вас может быть список, который фактически будет содержать список IField

interface IField 
{ 
object Data{get;set;}
}

interface IField<T> : IField
{
T TypedObject{get;set;}
}

Теперь вы можете иметь список, в который добавлен объект IField.

РЕДАКТИРОВАТЬ: Мне не нравитсяиспользовать базовые классы, если я действительно не должен, потому что тогда исключается возможность использования наследования позже.Наследование - это простое решение, но оно содержит целый ряд предостережений imo

...