我有这个通用类:
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。
但是我得到一个错误,说我需要少一个参数构造函数。但是接口没有构造函数。
我不知道这是否是正确的方法,但是我需要隔离我所有的页面类,从代码中删除所有类的引用/依赖项,更改为接口,以允许以更少的依赖项实现单元测试
我需要做什么?
谢谢。
答案 0 :(得分:0)
首先,您的问题不正确。您提供的代码不会产生该错误,因为您对类没有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);
}
}
}
}