c# - 如何使泛型类实现接口
问题描述
我有这个通用类:
public static class ListBuilder<T> where T : class
{
public static void Build(XmlElement element, string elementeName, ref List<T> lista)
{
XmlNodeList nl = element.GetElementsByTagName(elementeName);
if (nl != null && nl.Count > 0)
{
for (int i = 0; i < nl.Count; i++)
{
element = (XmlElement)nl.Item(i);
T item = (T)Activator.CreateInstance(typeof(T), element);
if (!lista.Contains(item))
lista.Add(item);
}
}
}
}
我从我项目的很多部分调用这个方法:
Util.ListBuilder<Alerta>.Build(element, "alerta", ref retorno);
我需要翻转所有页面,减少耦合,因此,我现在正在转换我的所有代码以便能够接收单元测试。
我的第一步是删除耦合声明,代之以类似的东西:
private Alerta _alerta;
进入:
private IAlerta _alerta;
所以,我需要将上面的调用转换成这样的:
Util.ListBuilder<IAlerta>.Build(element, "alerta", ref retorno);
但是,当我尝试将我的 Util 方法转换为接受它时,就像这样:
public static class ListBuilder<T> where T : IBaseInterface
{
public static void Build(XmlElement element, string elementeName, ref List<T> lista)
{
XmlNodeList nl = element.GetElementsByTagName(elementeName);
if (nl != null && nl.Count > 0)
{
for (int i = 0; i < nl.Count; i++)
{
element = (XmlElement)nl.Item(i);
T item = (T)Activator.CreateInstance(typeof(T), element);
if (!lista.Contains(item))
lista.Add(item);
}
}
}
}
public interface IBaseInterface
{
}
public interface IAlerta : IBaseInterface
{
int Id { get; set; }
string Titulo { get; set; }
string Mensagem { get; set; }
DateTime DataAlerta { get; set; }
}
public class Alerta : IAlerta
{
public int Id { get; set; }
public string Titulo { get; set; }
public string Mensagem { get; set; }
public DateTime DataAlerta { get; set; }
}
IBaseInterface 在我所有的接口中都实现了。
但是我收到一个错误,说我需要一个无参数的构造函数。但是接口没有构造函数。
我不知道这是否是正确的方法,但我需要隔离我所有的页面类,从代码中删除所有类引用/依赖项,更改为接口,以允许实现单元测试,减少依赖项。
我需要做什么 ?
谢谢。
解决方案
首先,你的问题是不正确的。您提供的代码不会给出该错误,因为您对类没有new()
约束并且您Activator.CreateInstance
使用一个参数进行调用。
但实际上你无论如何都不能实例化一个接口。您将需要重新考虑您的设计。ListBuilder 类中的这个方法是罪魁祸首:
T item = (T)Activator.CreateInstance(typeof(T), element);
您要求运行时实例化 的实例T
,在您的情况下是IAlerta
,因此是接口类型:
Util.ListBuilder<IAlerta>.Build(element, "alerta", ref retorno);
这意味着在这种情况下,上面的通用代码转换为
IAlerta item = (IAlerta)Activator.CreateInstance(typeof(IAlerta), element);
这确实总是会失败,因为您无法实例化接口。
你可以做什么:
- 像以前一样用具体类型调用
Build
方法(你为什么要准确地引入接口?这似乎没有必要,因为你的Alerta
类是一个简单的对象) 传递一个函数
Func<XElement,T>
来指示该方法如何构造 的实例T
,如下所示:public static class ListBuilder<T> where T : IBaseInterface { public static void Build(XmlElement element, string elementeName, ref List<T> lista, Func<XElement,T> ctor) { XmlNodeList nl = element.GetElementsByTagName(elementeName); if (nl != null && nl.Count > 0) { for (int i = 0; i < nl.Count; i++) { element = (XmlElement)nl.Item(i); T item = ctor(element); if (!lista.Contains(item)) lista.Add(item); } } } }
推荐阅读
- reactjs - 如何在时间间隔内用本机反应模糊图像?
- c++ - 在异步模式下使用 boost 进程运行进程并超时
- javascript - Blogger:带有自动阅读功能的可点击缩略图
- r - R 如何从相同维度矩阵的列表中生成汇总矩阵?
- php - 适用于 PHP 的 AWS 开发工具包生成 CloudWatch 事件 (putEvents) 的示例
- java - @ConditionalOnProperty 默认 bean 工作不正确
- swift - 无法在 swift 中使用 CNContactViewController 使用联系人的编辑功能
- batch-file - 命令行 检测网络适配器名称并更改 IP
- ssl - 如何在 heroku 中设置 .app 域(https 是强制性的)
- python - 如何先执行嵌套列表