I have a third-party, closed source application that exports a COM interface, which I am using in my C#.NET application through Interop. This COM interface exports many objects that all show up as System.Object until I cast them to the appropriate interface type. I want to assign an property of all of these objects. Thus:
foreach (object x in BigComInterface.Chickens)
{
(x as Chicken).attribute = value;
}
foreach (object x in BigComInterface.Ducks)
{
(x as Duck).attribute = value;
}
But assigning the property is likely (for application-specific reasons that are unavoidable) to throw Exceptions from which I want to recover, so I really want a try/catch around each one. Thus:
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...
}
}
Obviously, it would be so much cleaner to do this:
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...
}
}
See the problem? My x value can be of any type, so the compiler can't resolve .attribute. Chicken and Duck are not in any kind of inheritance tree and they do not share an interface that has .attribute. If they did, I could put a constraint for that interface on T. But since the class is closed-source, that's not possible for me.
What I want, in my fantasy, is something like a constraint requiring the argument to have the .attribute property regardless of whether it implements a given interface. To wit,
void SetAttribute<T>(T x, System.Object value) where T:hasproperty(attribute)
I'm not sure what to do from here other than to cut/paste this little try/catch block for each of Chicken, Duck, Cow, Sheep, and so on.
My question is: What is a good workaround for this problem of wanting to invoke a specific property on an object when the interface that implements that property cannot be known at compile time?