public interface IParser<T> where T: new()
{
    IList<T> Parse();
}

以上接口(interface)由以下抽象类实现
public abstract class BaseParser<T>: IParser<T> where T : new()
{
   protected abstract string Sql { get;}
   public List<T> Parse()
   {
      // do parsing
      Console.WriteLine(Sql);
   }
}

以下是上述抽象类的两个具体实现
public class EMailParser: BaseParser<Email>
{
    protected override string Sql
    {
        get
        {
            return @"SELECT * FROM emails";
        }
    }
}

public class UrlParser : BaseParser<Url>
{
    protected override string Sql
    {
        get
        {
            return @"SELECT * From Url";
        }
    }
}

用法:
class Program
{
    static void Main(string[] args)
    {
       if(args[1] == "url")
          Parser<Url>();
       else
          Parser<Email>();
    }
    static void Parse<T>()
    {
       // Create instance based on typof T and then assign to implementaion
       IParser<T> parser = typeof(T) == typeof(Url) ? new UrlParser(): new EmailParser();
       parser.Parse();
    }
}

我想根据 EmailParser 方法中提供的泛型类型创建 UrlParserProgram.Main 的实例,并将其分配给 BaseParser (抽象类)实现的接口(interface)。我怎样才能做到这一点?我知道我可以通过如下修改 Program.Parse<T> 来解决这个问题
static void Parse<T>() where T: new()
{
    IParser<T> parser = typeof(T) == typeof(Url) ? new UrlParser() as BaseParser<T> : new EmailParser() as BaseParser<T>;
    parser.Parse();
}

但是我想知道为什么我不能将子类实例分配给抽象类实现的接口(interface)??

我不明白为什么以下行不起作用
IParser<T> parser = typeof(T) == typeof(Url) ? new UrlParser(): new EmailParser();

以及为什么这条线有效
IParser<T> parser = typeof(T) == typeof(Url) ? new UrlParser() as BaseParser<T> : new EmailParser() as BaseParser<T>;

根据@nawfal 的回答,这一行也不应该起作用,因为 BaseParser 和 BaseParser 是不同的类型。 BaseParser 中的 IParser 是否存在隐式大小写?

最佳答案

因为 UrlParserEmailParser 之间没有隐式转换。它们都分别回到 BaseParser<Url>BaseParser<Email> (或 IParser<Url>IParser<Email> ),就编译器而言,它们是不同的类型。

我会保留一本字典来保存类型信息的映射,然后使用反射。类似的东西(未测试):

static Dictionary<string, Type> typeInfos = new Dictionary<string, Type>
{
    { "url", typeof(Url) },
    { "email", typeof(Email) },
    // and so on
};

你也是,
class Program
{
    static void Main(string[] args)
    {
        Parse(args[1]);
    }

    static void Parse(string type)
    {
        var parserType = typeof(BaseParser<>)
            .Assembly // or whatever the assembly is
            .GetTypes()
            .First(t => t.BaseType?.GetGenericArguments().FirstOrDefault() == typeInfos[type]);
        dynamic parser = Activator.CreateInstance(parserType);
        parser.Parse();
    }
}

使用表达式树和/或缓存事物来加快速度。

更新: 不,BaseParser<T>BaseParser<T> 是完全一样的东西。 T 在您的泛型方法中一次只能有一个值。真正的问题是如何转换 new UrlParser() as BaseParser<T> 。在通用上下文中,可以使用 as 将任何内容转换为任何内容 C# 规则在那里有点宽松(我不知道规范中的哪个部分)。

关于C#:将子类实例分配给抽象类实现的接口(interface),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37774023/

10-10 23:11