微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

实现一个非泛型的静态工厂方法,从字符串输入创建各种泛型类不使用“动态”类型

如何解决实现一个非泛型的静态工厂方法,从字符串输入创建各种泛型类不使用“动态”类型

我有一组从解析的 XML 中定义和填充的类。

作为其中的一部分,我希望能够动态实例化特定类型的集合类,如 XML 指定的那样(在本例中,用于管理/实例化异常)。

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

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

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

因此,为了达到目标,我首先实现了几个相关的静态类(在别处定义):

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

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

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

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

我对此感到很不舒服,因为我不喜欢结果的模糊性/不确定性,并且因为随后处理该结果可能会更加麻烦/复杂。我更愿意更具体地指定返回类型,然后以某种方式适当地强制转换/限定它,例如(是的,我知道这不是有效!):

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<> 在此语法/上下文中无效。 (生成“CS7003:意外使用未绑定的通用名称”),并且两者都不是仅使用 ExceptionGroup生成:“CS0305:使用通用类型 'ExceptionGroup' 需要 1 个类型参数。”)

所以,IS 有一种方法可以通过强(更)类型来实现这一点,通过一些其他语法或机制,更精确地描述结果,或者使用 dynamic,所有在随后的相关开销中,实际上是实现此目的的唯一方法吗?

解决方法

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

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

...然后从那个一个派生我的通用类:

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

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

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

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

...基本上达到预期的结果,尽管有些麻烦/尴尬。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。