Próbuję napisać metodę, która pobiera wszystkie ObservableCollections w viewModel i rzuca każdy jako ObservableCollection<object>
. Korzystając z refleksji, udało mi się uzyskać każdy z nich ObservableCollection<T>
jako obiekt, ale mam trudności z rzuceniem tego obiektu na obiekt ObservableCollection<object>
. Oto mój kod do tej pory:
var props = viewModel.GetType().GetProperties();
Type t = viewModel.GetType();
foreach (var prop in props)
{
if (prop.PropertyType.Name == "ObservableCollection`1")
{
Type type = prop.PropertyType;
var property = (t.GetProperty(prop.Name)).GetValue(viewModel);
// cast property as an ObservableCollection<object>
}
}
Czy ktoś wie, jak powinienem postępować?
Odpowiedzi:
2 dla odpowiedzi № 1Porównywanie nazwy typu z ciągiem jest złym pomysłem. Aby stwierdzić, że jest ObservableCollection
możesz użyć:
if (prop.PropertyType.IsGenericType &&
prop.PropertyType.GetGenericTypeDefinition() == typeof(ObservableCollection<>))
Wartość może zostać wyodrębniona i przekształcona jako taka:
foreach (var prop in viewModel.GetType().GetProperties())
{
if (prop.PropertyType.IsGenericType &&
prop.PropertyType.GetGenericTypeDefinition() == typeof(ObservableCollection<>))
{
var values = (IEnumerable)prop.GetValue(viewModel);
// cast property as an ObservableCollection<object>
var collection = new ObservableCollection<object>(values.OfType<object>());
}
}
Jeśli chcesz je połączyć w jedną kolekcję, możesz to zrobić:
var values = viewModel.GetType().GetProperties()
.Where(p => p.PropertyType.IsGenericType)
.Where(p => p.PropertyType.GetGenericTypeDefinition() == typeof(ObservableCollection<>))
.Select(p => (IEnumerable)p.GetValue(viewModel))
.SelectMany(e => e.OfType<object>());
var collection = new ObservableCollection<object>(values);
1 dla odpowiedzi nr 2
Odpowiedz na to pytanie tutaj: https://stackoverflow.com/a/1198760/3179310
Ale żeby wyjaśnić twoją sprawę:
if (prop.PropertyType.Name == "ObservableCollection`1")
{
Type type = prop.PropertyType;
var property = (t.GetProperty(prop.Name)).GetValue(viewModel);
// cast property as an ObservableCollection<object>
var col = new ObservalbeCollection<object>(property);
// if the example above fails you need to cast the property
// from "object" to an ObservableCollection<T> and then execute the code above
// to make it clear:
var mecol = new ObservableCollection<object>();
ICollection obscol = (ICollection)property;
for(int i = 0; i < obscol.Count; i++)
{
mecol.Add((object)obscol[i]);
}
// the example above can throw some exceptions but it should work in most cases
}
0 dla odpowiedzi № 3
Możesz użyć Cast<T>()
metoda rozszerzenia, ale nie zapomnij, używając tegoMetoda (poniżej) spowoduje utworzenie nowej instancji, więc zdarzenia z oryginału nie działają. Jeśli nadal chcesz otrzymywać zdarzenia, powinieneś utworzyć wokół niego opakowanie.
var prop = viewModel.GetType("ObservableCollection`1");
var type = prop.PropertyType;
var propertyValue = (t.GetProperty(prop.Name)).GetValue(viewModel);
// cast property as an ObservableCollection<object>
var myCollection = new ObservableCollection<object>(
((ICollection)propertyValue).Cast<object>());
}