Создайте общий список

Я хочу создать общий список таких объектов, как:

public static class TablesClass
{
    private static IList<Tables<T>> TablesInstance { get; set; }

    static TablesClass() => Tables = new List<Tables<T>>();
    public static void AddTable(Table<t> table) => Tables.Add(table);
}

Я не могу изменить Tables<T>, это класс пакета nuget.

Как я могу этого добиться? Все, что я пробовал, просто не работает (установка типа T для класса, использование объекта вместо T и приведения - нежелательное решение).

Кто-нибудь может мне помочь?

Вероятно, вам нужно сделать TablesClass generic => public static class TablesClass<T>

Camilo Terevinto 10.08.2018 14:57

Но таким образом у меня не может быть нескольких типов в TablesInstance.

Jake Manet 10.08.2018 14:59

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

Camilo Terevinto 10.08.2018 15:03

Вам нужно сообщить компилятору, какой тип T где-то должен быть. Если вы хотите иметь возможность добавлять в список разные типы объектов, T должен быть общим типом для всех этих объектов, например, object.

mm8 10.08.2018 15:06

Нежелательное решение кажется единственным решением, которое может у вас быть. Проще говоря, если вы хотите иметь возможность использовать список со всеми видами объектов таблиц, вам либо нужен базовый тип, который не использует универсальные шаблоны, либо вам нужно использовать объект вместо T. В любом случае у вас не будет возможности для доступа к типам в списке (например, тип таблицы i-го элемента списка) во время компиляции, поэтому на самом деле не имеет значения, какой путь вы выберете.

welrocken 10.08.2018 15:26

@JakeManet: But in this way i can't have multiple types on TablesInstance. Вы неправильно понимаете вариант использования дженериков. Каждый экземпляр объекта List<T> (List<string>, List<int>, ...) всегда будет иметь только тип один. Вы можете делать такие вещи, как List<object>, чтобы добавить много классов в свой список, но у этого есть серьезные недостатки (и обычно это не рекомендуется делать).

Flater 10.08.2018 15:57

@Flater, вы можете добавить в список такие объекты, как Tables <T>.

Jake Manet 10.08.2018 16:00

@JakeManet Не без предварительного определения T. Существует разница между универсальным типом класса и конкретным (конкретным) типом, когда этот класс используется

Flater 10.08.2018 16:37
2
8
122
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

TablesClass не является универсальным классом, и вы не сообщаете компилятору, какой тип T где-то должен быть.

Если вы хотите иметь возможность добавлять разные типы объектов в один и тот же список IList<Tables<T>>, Tдолжен будет общим базовым типом для всех этих объектов.

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

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

Ваш класс nuget должен иметь следующий стиль:

public abstract class Tables
{
}

//the Generic class must has a base, by which you can list them
public class Tables<T> : Tables // where T: something base class of your object
{
    //...
}

тогда ваш класс должен быть:

public static class TablesClass
{
    //Search source code of your Nuget package, find its base class of Generic class, the list must be defined as its base
    private static IList<Tables> Tables { get; set; }

    static TablesClass()
    {
        Tables = new List<Tables>();
    }

    public static void AddTable(Tables table)
    {
        Tables.Add(table);
    }
}

тогда вы можете использовать это так:

public class Test
{
    public static void Mains()
    {
        TablesClass.AddTable(new Tables<A>());
        TablesClass.AddTable(new Tables<B>());
        TablesClass.AddTable(new Tables<C>());
    }
}

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

Попробуйте такой класс:

public class Repository
{
    private Dictionary<Type, Dictionary<string, object>> _store
        = new Dictionary<Type, Dictionary<string, object>>();

    public void Store<T>(string key, T value)
    {
        if (!_store.ContainsKey(typeof(T)))
        {
            _store.Add(typeof(T), new Dictionary<string, object>());
        }
        _store[typeof(T)][key] = value;
    }

    public T Fetch<T>(string key)
    {
        return (T)_store[typeof(T)][key];
    }

    public bool TryFetch<T>(string key, out T value)
    {
        var success = _store.ContainsKey(typeof(T)) && _store[typeof(T)].ContainsKey(key);
        value = success ? this.Fetch<T>(key) : default(T);
        return success;
    }

    public bool TryInject<T>(string key, Action<T> inject)
    {
        var success = this.TryFetch<T>(key, out T value);
        if (success)
        {
            inject(value);
        }
        return success;
    }       
}

Затем вы можете строго ввести объекты в репозиторий (коллекцию) и извлечь их с помощью строгого типа следующим образом:

var repository = new Repository();

repository.Store("a", new TableA());
repository.Store("b", new TableB());
repository.Store("c", new TableC());
repository.Store("d", new TableD());

/* Somewhere else in your code */
TableA a = repository.Fetch<TableA>("a");
TableB b = repository.Fetch<TableB>("b");
TableC c = repository.Fetch<TableC>("c");
TableD d = repository.Fetch<TableD>("d");

Значение ключа (например, «a») является необязательным - вы можете удалить его из кода, - но оно полезно, если вам нужно сохранить более одного объекта определенного типа.

Ответ принят как подходящий

Очень простое решение: List<dynamic>.

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

Jake Manet 17.08.2018 11:18

Другие вопросы по теме