Приведение объекта в общий список - PullRequest
13 голосов
/ 14 мая 2010

У меня есть 3 списка типов генериков.

List<Contact> = new List<Contact>();
List<Address> = new List<Address>();
List<Document> = new List<Document>();

И сохраните его в переменной с типом объекта. Теперь мне нужно выполнить Cast Back to List, чтобы выполнить foreach, например:

List<Contact> = (List<Contact>)obj;

Но содержимое obj меняется каждый раз, и у меня вот так:

List<???> = (List<???>)obj;

У меня есть другая переменная, удерживающая текущий объект. Тип:

Type t = typeof(obj);

Могу ли я сделать что-то подобное ??:

List<t> = (List<t>)obj;

Obs: у меня нет текущего типа в списке, но мне нужно разыграть, и вместо этого у меня нет другой формы:

List<Contact> = new List<Contact>();

Ответы [ 8 ]

30 голосов
/ 14 мая 2010

Какая неприятная проблема. Попробуйте это:

List<Contact> c = null;
List<Address> a = null;
List<Document> d = null;

object o = GetObject();

c = o as List<Contact>;
a = o as List<Address>;
d = o as List<Document>;

Между c, a и d есть 2 нуля и 1 ненулевое или 3 нуля.


Взять 2:

object o = GetObject();
IEnumerable e = o as IEnumerable;
IEnumerable<Contact> c = e.OfType<Contact>();
IEnumerable<Address> a = e.OfType<Address>();
IEnumerable<Document> d = e.OfType<Document>();
24 голосов
/ 22 апреля 2013

Много проб и ошибок дали мне это на SL 5, но это также должно работать на обычном C #. Вам также нужно добавить LINQ в свой список использования, чтобы последняя половина работала.

    List<object> myAnythingList = (value as IEnumerable<object>).Cast<object>().ToList()

Наслаждайтесь!

2 голосов
/ 10 октября 2013

У меня была та же проблема, и я решил ее, посмотрев на цель брошенных объектов Вы действительно должны привести его к определенным (закрытым) родовым типам? В моем случае (открытый) универсальный тип имел интерфейс, к которому я его приводил.

var list = obj as IUsefulInterface;

list.MethodThatIAmInterestedIn();
1 голос
/ 06 января 2017

У меня была эта проблема при написании атрибута валидации, когда я получил объект из ValidationContext и знал, что это должен быть список, а не то, чем он был. Он выдал исключение, когда я попытался привести его к типу IEnumerable<object>, но его можно было сгенерировать как IEnumerable, что затем позволило .Cast<object>() через linq.

В итоге получилось:

var enumerable = listObject as IEnumerable;
var list = enumerable.Cast<object>().ToList();
1 голос
/ 14 мая 2010

Такое общее решение (создание экземпляра типа с универсальным параметром на основе объекта System.Type) невозможно. Если вы действительно имеете дело с этими тремя типами, то вам повезло, потому что это довольно просто:

Type t = typeof(obj);

if (t == typeof(List<Contact>)) {
    var contactList = (List<Contact>)obj;
    // do stuff with contactList

} else if (t == typeof(List<Address>)) {
    var addressList = (List<Address>)obj;
    // do stuff with addressList

} else if (t == typeof(List<Document>)) {
    var documentList = (List<Document>)obj;
    // do stuff with documentList
}
0 голосов
/ 16 января 2018

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

string jsonString = JsonConvert.SerializeObject(myObject);
jsonString = "{ values:" + jsonString + "}";

JObject j = JObject.Parse(jsonString);

//now we can iterate over the list
foreach (var x in j["values"])
{
    string name = x.ToString();
    ...
}
0 голосов
/ 14 мая 2010

Нет, вы не можете приводить без обхода углов (это: отражение), параметры универсального типа должны быть известны во время компиляции. Конечно, вы можете сделать что-то вроде этого:

content.Where(o => o is type).ToList().Foreach(stuff);

0 голосов
/ 14 мая 2010

Возможно, вам понадобится:

if(object is List)
{
    list = (List)object
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...