实现一个非泛型的静态工厂方法以从字符串输入创建各种泛型 类(不使用 "dynamic" 类型)

Implement a non-generic, static Factory method to create various Generic Classes from string input (without using "dynamic" type)

我有一组 classes,它们是根据解析的 XML.

定义和填充的

作为其中的一部分,我希望能够为特定类型动态实例化集合 classes,如 XML 所指定(在这种情况下,管理/实例化异常)。

所以我有一个class,大致定义如下:

public class ExceptionGroup<T> : BaseCollectionClass<Exception> where T : Exception 
{
    // contents of this class don't really matter
}

当我处理 XML 时,我会将异常派生类型的名称包含在一个字符串中(即“ArgumentNullException”、“InvalidDataException”、“IndexOutOfRangeException”等),以及将用于填充生成的异常的内容(消息)(也是一个字符串)when/if 它被抛出。

所以,为了到达我想去的地方,我首先实现了几个相关的静态 classes(在别处定义):

// 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; 
}

使用这些 classes,我可以获取一个输入字符串并以已知的、现有的 C# 类型 class(假设输入字符串有效)结束,该类型派生自异常 class。现在我想构建一个可以创建新的 ExceptionGroup<T> 对象的工厂方法,其中“T”是从原始字符串派生的对象类型。

有点通过使用dynamic类型作为工厂的return类型来管理这个,如下所示:

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;
}

虽然我对此感到非常不舒服,因为我不喜欢结果的模糊/不确定性,并且因为随后处理该结果可能会更多 cumbersome/complex。我更愿意 更具体地指定 return 类型,然后以某种方式适当地 cast/qualify 它,例如(是的,我 知道这是无效的!):

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;
}

...但是,当然 ExceptionGroup<> 在此 syntax/context 中无效。 (生成“CS7003:意外使用未绑定的通用名称”),并且两者都不只是使用 ExceptionGroup(生成:“CS0305:使用通用类型 'ExceptionGroup' 需要 1 个类型参数。”)

所以,IS 有一种方法可以通过一些其他语法或机制使用强(呃)类型来完成此操作,并获得更精确描述的结果,或者正在使用 dynamic,以及所有后续相关的开销,从字面上看,这是实现此目标的唯一方法吗?

虽然我希望可能有一个更简单/简洁的解决方案(如果是的话,我很乐意看到它!)Sweeper 的一些回顾性提示让我意识到我基本上可以通过注入开销来绕过这个问题一个新的抽象祖先 class:

public abstract class ExceptionGroupFoundation : BaseCollectionClass<Exception>
{
    public ExceptionGroupFoundation( object[] args = null ) : base( args ) { }

    // Implement necessary common accessors, methods, fields, properties etc here...
    // (preferably "abstract" as/when/where possible)
}

...然后从 that 派生出我的通用 class:

public class ExceptionGroup<T> : ExceptionGroupFoundation where T : Exception 
{
    public ExceptionGroup( object[] args = null ) : base( args ) { }

    // contents of this class don't really matter
}

... 然后使用新抽象 class 作为 return 类型声明我的工厂方法:

public static ExceptionGroupFoundation CreateGroup( string exceptionTypeName )
{
    Type excType = DeriveType( exceptionTypeName );
    if ( !(excType is null) )
    {
        Type[] types = new Type[] { excType };
        Type groupType = typeof( ExceptionGroup<> ).MakeGenericType( types );
        return (ExceptionGroupFoundation)Activator.CreateInstance( groupType );
    }
    return null;
}

...从根本上达到预期的结果,尽管有点 cumbersomely/awkwardly。