如何制作一个通用的类实现接口

时间:2018-08-24 06:24:25

标签: c# dependency-injection

我有这个通用类:

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。

但是我得到一个错误,说我需要少一个参数构造函数。但是接口没有构造函数。

我不知道这是否是正确的方法,但是我需要隔离我所有的页面类,从代码中删除所有类的引用/依赖项,更改为接口,以允许以更少的依赖项实现单元测试

我需要做什么?

谢谢。

1 个答案:

答案 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);
                }
             }
        }
    }