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
方法中提供的泛型类型创建 UrlParser
或 Program.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 是否存在隐式大小写?
最佳答案
因为 UrlParser
和 EmailParser
之间没有隐式转换。它们都分别回到 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/