Словарь общих списков или разных типов

17

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

Key        Value
string     List<T>
string     List<U>
string     List<V>
string     List<U>
...

В настоящее время я использую Dictionary<string, IList> , а затем извлекал строго типизированный список из каждого словаря KeyValuePair<string, IList> pair , как показано ниже:

Type layerType = pair.Value.GetType().GetGenericArguments()[0];
List<layerType> objectsClicked = pair.Value as List<layerType>;

Есть ли лучший способ сделать это?

[Изменить] Как уже отмечалось, вышесказанное не компилируется, извинения - это то, что вы получаете, когда задаете вопрос, пока вы все еще работаете над чем-то. Еще несколько объяснений. Я делаю основной просмотрщик пространственных данных. Окончательный вид состоит из группы Layer<T> s. Каждый слой предоставляет делегату возможность отображать его тип (с учетом смещения и масштаба) и способ проверить, какие из его объектов находятся в текущем окне. Для тестирования попадания я хотел бы получить список для каждого слоя, из которого были удалены объекты. Этот список будет List<Point> для слоя Point и т. Д. Группировка хитов из всех Layer<T> s будет тогда набором строго типизированных списков.

    
задан Matthew Finlay 18.02.2011 в 06:37
источник

4 ответа

35

Как насчет Dictionary<string, dynamic> при условии, что вы находитесь на C # 4

Dictionary<string, dynamic> Dict = new Dictionary<string, dynamic>();
Dict.Add("int", new List<int>());
Dict.Add("string", new List<string>());

Dict["int"].Add(12);
Dict["string"].Add("str");

foreach (KeyValuePair<string, dynamic> pair in Dict) {
   Type T = pair.Value.GetType();
   Console.WriteLine(T.GetGenericArguments()[0].ToString());
}

Это выводит

  

System.Int32

     

System.String

Это то, что вы ищете?

    
ответ дан Adam Rackis 18.02.2011 в 06:41
источник
2

Использование Dictionary<string, IList> возможно только решение. Но ваш код неправильный, вы не можете использовать такие дженерики. Вы не можете создать динамическую динамику типа.

Общая проблема с вашей потребностью заключается в том, что она несовместима с языком с сильным типом, подобным C #. В строго типизированном языке вы должны знать, какой тип типа ТОЧНО. Но это можно сделать обычными способами. Также ваше понимание дженериков неверно. Его единственное расширение времени компиляции для типа.

И общая идея . В вашем случае, используя какой-то вид ООП, поиск типов, которые вы сохраняете в этих списках. Это будет намного лучше и безопаснее, и не заставит всех, кто смотрит на ваш код, вырвать его волосы.

    
ответ дан Euphoric 18.02.2011 в 06:46
источник
2

Я собираюсь взять промежуточное звено между Эйфориком и Адамом, вы должны использовать как IList , так и dynamic . Это то, что я считаю более правильным:

var dict = new Dictionary<string, IList>();
dict.Add("u", new List<U>());
dict.Add("v", new List<V>());

// in case of members you know they exist on an IList
dict["u"].Add(new U());
dict["v"].Add(new V());

// in case you know what you are going to get back, in which case you should cast
var uProperty = (dict["u"][0] as U).UProperty
var vProperty = (dict["v"][0] as V).VProperty

// in case your're not sure of     
(dict[someKey] as dynamic)[someIndex].SomeMember...;

Все это намного проще, чем полагаться на отражение. Основная идея - объявить тип значения словаря как IList , чтобы сделать ваши намерения более ясными спереди, а использовать dynamic , чтобы облегчить отражение и сделать код короче.

    
ответ дан nawfal 22.03.2016 в 06:43
источник
0

Я действительно думаю, что более чистый подход - создать оболочку для вашего словаря:

public class GlobalStore
{
    private readonly IDictionary<Type, IEnumerable> _globalStore;

    public GlobalStore()
    {
        _globalStore = new ConcurrentDictionary<Type, IEnumerable>();
    }

    public IEnumerable<T> GetFromCache<T>()
        where T : class 
    {
        return (IEnumerable<T>) _globalStore[typeof(T)];
    }

    public void SetCache<T>(IEnumerable<T> cache)
        where T : class
    {
        _globalStore[typeof(T)] = cache;
    }
}

Вот тест:

[TestClass]
public class GlobalStoreTest
{
    [TestMethod]
    public void GlobalStore_Test()
    {
        //Arrange
        var globalStore = new GlobalStore();
        globalStore.SetCache(new List<ClientModel>
        {
            new ClientModel
            {
                ClientId = 1,
                ClientName = "Client1"
            },
            new ClientModel
            {
                ClientId = 2,
                ClientName = "Client2"
            }
        });

        //Act
        var clients = globalStore.GetFromCache<ClientModel>();

        //Assert
        Assert.AreEqual(2, clients.Count());
    }
}
    
ответ дан ODawg G 07.05.2017 в 00:15
источник