У меня есть стороннее закрытое исходное приложение, которое экспортирует COM-интерфейс, который я использую в своем приложении С#.NET через Interop. Этот COM-интерфейс экспортирует множество объектов, все из которых отображаются как System.Object, пока я не передам их соответствующему типу интерфейса. Я хочу назначить свойство всех этих объектов. Таким образом:
foreach (object x in BigComInterface.Chickens)
{
(x as Chicken).attribute = value;
}
foreach (object x in BigComInterface.Ducks)
{
(x as Duck).attribute = value;
}
Но присваивание свойства, скорее всего, (по причинам, связанным с конкретным приложением, которые неизбежны), чтобы выбрасывать Исключения, из которых я хочу восстановить, поэтому я действительно хочу попробовать/поймать каждого из них. Таким образом:
foreach (object x in BigComInterface.Chickens)
{
try
{
(x as Chicken).attribute = value;
}
catch (Exception ex)
{
// handle...
}
}
foreach (object x in BigComInterface.Ducks)
{
try
{
(x as Duck).attribute = value;
}
catch (Exception ex)
{
// handle...
}
}
Очевидно, для этого было бы гораздо более чистым:
foreach (object x in BigComInterface.Chickens)
{
SetAttribute<Chicken>(x as Chicken, value);
}
foreach (object x in BigComInterface.Ducks)
{
SetAttribute<Duck>(x as Duck, value);
}
void SetAttribute<T>(T x, System.Object value)
{
try
{
x.attribute = value;
}
catch
{
// handle...
}
}
Увидеть проблему? Мое значение x может быть любого типа, поэтому компилятор не может разрешить.трибут. Цыпленок и утка не имеют никакого дерева наследования и не имеют интерфейса с атрибутом. Если бы они это сделали, я мог бы установить ограничение для этого интерфейса на T. Но поскольку класс является закрытым, это невозможно для меня.
То, что я хочу, в моей фантазии, является чем-то вроде ограничения, требующего, чтобы аргумент имел свойство .attribute независимо от того, реализует ли он данный интерфейс. Для этого
void SetAttribute<T>(T x, System.Object value) where T:hasproperty(attribute)
Я не уверен, что делать дальше, кроме как вырезать/вставить этот маленький блок try/catch для каждого из Chicken, Duck, Cow, Sheep и т.д.
Мой вопрос: что является хорошим обходным путем для этой проблемы, требующей вызова определенного свойства для объекта, когда интерфейс, реализующий это свойство, не может быть известен во время компиляции?