- If something goes wrong, it simply tries the next one.
- If it finds the appropriate type (i.e. the one which instance was successfully created), it caches this info and does not use sequential search process for it further.
- If there is no such a type, it finally returns null (no associate was found).
But since there is no overload of Activator.CreateInstance allowing to get e.g. null instead of created type in case of error, we should:
- Either catch & suppress some exceptions it throws. That's what we have now.
- Or manually check all the preconditions, which is pretty complex. We already check some of them to minimize the count of thrown exceptions, but there are still some pretty complex cases where exceptions are thrown an caught. Typical exception message we have there now is "GenericArguments, 'System.Object', on 'Xtensive.Core.Comparison.ObjectComparer`1[T]' violates the constraint of type parameter 'T'.". So to avoid getting this exception, we must check generic arguments - their count constraints.
Obviously, second case seems ridiculous: .NET Framework already contains the code that can do this, and it works. But:
- This code throws an exception in case of error
- Visual Studio .NET does not provide a good way to suppress it (i.e. behave like it is normal control flow).
That's why I really miss [DebuggerSkipThrownException(typeof(XxxException))] attribute. Imagine, when it is applied to some method, an exception of XxxException type thrown in its stack frame or anywhere above on stack must not lead to break in Visual Studio .NET. If we have this, it could be an ideal solution of such problems.
But since Microsoft doesn't care much about this (although I hope it will), we must implement our own, non-ideal one - which will make the code much less clear...