I have a set of classes which are defined and populated from parsed XML.
As part of this, I want to be able to dynamically instantiate collection classes for particular types, as specified by the XML (in this case, to manage / instantiate exceptions).
So I have a class, approximately defined as follows:
public class ExceptionGroup<T> : BaseCollectionClass<Exception> where T : Exception
{
// contents of this class don't really matter
}
When I process the XML, I will have the name of the Exception-derived type contained in a string (i.e. "ArgumentNullException", "InvalidDataException", "IndexOutOfRangeException" etc.), as well as the content (message) that will be used to populate the generated Exception (also a string) when/if it's thrown.
So, to get where I'm trying to go, I first have implemented a couple of relevant static classes (defined elsewhere):
// Recursively determines if a supplied Type is ultimately derived from the Exception class:
public static bool IsException( Type type ) =>
(type == typeof( object )) ? false : (type == typeof(Exception)) || IsException( type.BaseType );
// Figures out if the specified string contains the name of a recognized Type
// and that the Type itself is genuinely derived from the Exception base class:
public static Type DeriveType( string name )
{
// If the string is null, empty, whitespace, or malformed, it's not valid and we ignore it...
if ( !string.IsNullOrWhiteSpace( name ) && Regex.IsMatch( name, @"^([a-z][\w]*[a-z0-9])$", RegexOptions.IgnoreCase ) )
try
{
Type excType = System.Type.GetType( name );
if ( IsException( excType ) ) return excType;
}
catch { }
// The type could not be determined, return null:
return null;
}
Using these classes, I can take an input string and end up with a known, existing, C# Type class (presuming the input string is valid) that's derived from the Exception class. Now I want to build a factory method that can create new ExceptionGroup<T> objects where "T" is the object type that's derived from the orignal string.
I've kind of managed this by using the dynamic type as the factory's return type as follows:
public static dynamic CreateExceptionGroup( string exceptionTypeName )
{
Type excType = DeriveType( exceptionTypeName );
if ( !(excType is null) )
{
Type groupType = typeof( ExceptionGroup<> ).MakeGenericType( new Type[] { excType } );
return Activator.CreateInstance( groupType );
}
return null;
}
I'm quite uncomfortable with this though, both because I dislike the ambiguity / uncertainty of the result, and because subsequently working with that result can be more cumbersome/complex. I'd much rather actually specify the return type more concretely, and then appropriately cast/qualify it in some manner, for example (yes, I know that this isn't valid!):
public static ExceptionGroup<> CreateGroup( string exceptionTypeName )
{
Type excType = DeriveType( exceptionTypeName );
if ( !(excType is null) )
{
Type[] types = new Type[] { excType };
Type groupType = typeof( ExceptionGroup<> ).MakeGenericType( types );
return (ExceptionGroup<>)Activator.CreateInstance( groupType );
}
return null;
}
...but, of course ExceptionGroup<> isn't valid in this syntax/context. (Generates "CS7003: Unexpected use of an unbound generic name"), and neither is merely using ExceptionGroup (Generates: "CS0305: Using the generic type 'ExceptionGroup' requires 1 type arguments.")
So, IS there a way to do this with strong(er) typing, via some other syntax or mechanism, with more precisely described results, or is using dynamic, with all of the subsequent associated overhead, literally the only way to accomplish this?