Передать тип интерфейса в качестве параметра

#c# #interface #parameters

#c# #интерфейс #параметры

Вопрос:

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

Допустим, я объявил несколько интерфейсов, которые были неравномерно реализованы для ряда объектов, которые все образуют единый список / коллекцию. Могу ли я написать вспомогательный метод, который будет принимать как объект из списка, так и тип интерфейса в качестве параметра и проверять, реализует ли объект интерфейс? Следующий код, очевидно, является мусором, но он иллюстрирует то, что я хочу сделать:

 private bool CheckType(object o, interface intrfce)
{
    try
    {
        object x = (object)(intrfce)o;
        return true;
    }
    catch (InvalidCastException e) 
    {
        return false
    }
}
 

На данный момент я просто планирую настроить перечисление для интерфейсов и потребовать, чтобы все классы предоставляли массив / список интерфейсов, которые они реализуют. Затем я могу просто проверить список перечислений, чтобы узнать, какие у них есть соответствующие интерфейсы (меня интересуют только созданные мной интерфейсы — я не после возврата IEnumerable и ICloneable т. Д.), Или я мог бы написать вспомогательные методы для каждого интерфейса. Мне просто было интересно, есть ли более элегантный способ сделать это?

Ответ №1:

Вы можете сделать это с помощью дженериков:

 private bool CheckType<T>(object o) {
    return o is T;
}
 

Вы называете это так:

 foreach (object o in myList) {
    if (CheckType<MyInterface>(o)) {
        ... // Do something
    }
}
 

Учитывая, насколько легко это сделать, вы могли бы также сделать это в самом условном.

Наконец, если вы хотите обрабатывать только объекты, реализующие определенный интерфейс в смешанном списке, вы можете сделать это с OfType помощью метода LINQ, например:

 foreach (MyInterface o in myList.OfType<MyInterface>()) {
   ...
}
 

Комментарии:

1. Спасибо, именно то, что мне было нужно!

Ответ №2:

Вы можете сделать что-то вроде:

 private bool CheckType(object o, params Type[] types)
{
    //you can optionally check, that types are interfaces
    //and throw exceptions if non-interface type was passed
    if(types.Any(type => !type.IsInterface))
        throw new Exception("Expected types to have only interface definitions");

    return types.All(type => type.IsAssignableFrom(o.GetType()));
}


CheckType(new List<int>(), typeof(IEnumerable), typeof(IList)); //returns true
CheckType(0, typeof(IEnumerable)); //return false
 

Чтобы проверить последовательность объектов, вы можете использовать что-то вместе:

 private bool CheckAllType(IEnumerable<object> items, params Type[] types)
{
    return items.All(item => CheckType(item, types));
}
 

Комментарии:

1. Это очень полезно. Мне нравится возможность передавать несколько типов интерфейсов в качестве параметров. Спасибо!