首页 > 解决方案 > 如何使泛型类实现接口

问题描述

我有这个通用类:

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 在我所有的接口中都实现了。

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

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

我需要做什么 ?

谢谢。

标签: c#dependency-injection

解决方案


首先,你的问题是不正确的。您提供的代码不会给出该错误,因为您对类没有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);
                }
             }
        }
    }
    

推荐阅读