Типизация коллекции объектом Type

191
24 января 2019, 13:20

Есть несколько коллекций:

private ObservableCollection<CivilRoom> _rooms = new ObservableCollection<CivilRoom>();
private ObservableCollection<CivilDoor> _doors = new ObservableCollection<CivilDoor>();
private ObservableCollection<WindowCivil> _windows = new ObservableCollection<WindowCivil>();
private ObservableCollection<CivilRamp> _ramps = new ObservableCollection<CivilRamp>();

Доступ к которым предоставляется через соответствующие свойства:

public ICollection<CivilRoom> Rooms => _rooms;
public ICollection<CivilDoor> Doors => _doors;
public ICollection<WindowCivil> Windows => _windows;
public ICollection<CivilRamp> Ramps => _ramps;

Для всех элементов в данных коллекциях в базовом классе определено событие:

public event EventHandler Deleting;

И метод который инициирует данное событие:

public void Delete()
    {
        Deleting?.Invoke(this, EventArgs.Empty);
    }

При добавлении элемента в любую из этих коллекций идет подписка на событие удаления этого элемента:

topologyItem.Deleting += OnElementDeleting;

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

private void OnElementDeleting(object sender, EventArgs e)
    {
        if (sender == null)
        {
            throw new ArgumentNullException(nameof(sender));
        }
        var targetCollection = GetType().GetProperties()
            .First(p => p.PropertyType.IsGenericType && 
                        p.PropertyType.GetGenericArguments()[0] == sender.GetType())
            .GetValue(this);
    }
Answer 1

У меня не так много времени и я уверен, что вы можете решить вашу задачу гораздо эффективней, чем с рефлексией (например, изменив тип события тут public event EventHandler Deleting; на нужный вам). Потому я вас просто предупрежу, что рефлексия - медленное зло, что ответ мой не будет блистать, но будет как то рабоать.

Итак, есть 2 класса

class One { }
class Two { }

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

class Test
{
    public ICollection<One> One { get; set; } = new ObservableCollection<One>();
    public ICollection<Two> Two { get; set; } = new ObservableCollection<Two>();
    public void Add(object item)
    {
        // find and call generic method
        var m = this.GetType().GetMethods()
                   .Where(x => x.Name == "Add" && x.IsGenericMethod).Single();
        var call = m.MakeGenericMethod(item.GetType());
        call.Invoke(this, new[] { item });  
    }
    // find property-collection with reflection
    public void Add<T>(T item)
    {
        foreach (var p in this.GetType().GetProperties())
            if (p.PropertyType == typeof(ICollection<T>))
                (p.GetValue(this) as ICollection<T>).Add(item);
    }   
}

Как использовать:

var t = new Test();
t.Add(new One()); // генерик
t.Add((object)new Two()); // object

Надеюсь, этого вам достаточно доя решения вашей задачи

READ ALSO
C# Ошибка в SingleTon?

C# Ошибка в SingleTon?

Есть файл кастомных конфигураций для нескольких клиентов, которые я держу в памяти через Single TonДолго все работало без проблем но тут внезапно...

187
C#, Xamarin ошибка System.IO.FileNotFoundException при XmlDocument.LoadXml(string)

C#, Xamarin ошибка System.IO.FileNotFoundException при XmlDocument.LoadXml(string)

Код который у меня, ошибка на последней строчке

176
C# объединение и сумма одинаковых элементов в List

C# объединение и сумма одинаковых элементов в List

подскажите, пожалуйста, как я могу получить сумму одинаковых элементов в двух списках? И добавить в конечный список уникальные элементы?

283