У меня есть стороннее приложение с закрытым исходным кодом, которое экспортирует интерфейс COM, который я использую в своем приложении C # .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 может быть любого типа, поэтому компилятор не может разрешить .attribute . Цыпленок и Утка не находятся в каком-либо дереве наследования и не имеют общего интерфейса, который имеет .attribute . Если бы они это сделали, я мог бы установить ограничение для этого интерфейса на T . Но так как класс с закрытым исходным кодом, для меня это невозможно.
В моей фантазии я хочу что-то вроде ограничения, требующего, чтобы аргумент имел свойство .attribute независимо от того, реализует ли он данный интерфейс. Для остроумия,
void SetAttribute<T>(T x, System.Object value) where T:hasproperty(attribute)
Я не уверен, что делать дальше, кроме как вырезать / вставить этот маленький блок try / catch для каждого из Цыпленка, Утки, Коровы, Овцы и т. Д.
У меня такой вопрос: как можно решить эту проблему, когда нужно вызвать конкретное свойство объекта, когда интерфейс, реализующий это свойство, не может быть известен во время компиляции?