需要依赖注入时,通用工厂是不可能的?

时间:2011-12-02 19:11:18

标签: c# .net generics factory

我正在尝试为我的服务工厂和dao工厂制作一些通用工厂,并且遇到了一些限制。

通常我的服务和dao工厂看起来像这样:

public static class PersonServiceFactory
{
    private static PersonService personService;

    public static PersonService GetInstance()
    {
        if (personService == null)
        {
            PersonDao personDao = PersonDaoFactory.GetInstance();
            personService = new PersonService(personDao);

        }

        return personService;
    }
}

public static class PersonDaoFactory
{
    private static PersonDao personDao;

    internal static PersonDao GetInstance()
    {
        if (personDao == null)
        {
            personDao = new PersonDao();

        }

        return personDao;
    }
}

然后我尝试做一个通用工厂:

 public abstract class EntityDaoFactory<daoClass>
        where daoClass : class, new()
    {
        private static daoClass factorySupportClass;

        internal static daoClass GetInstance()
        {
            if (factorySupportClass == null)
            {
                factorySupportClass = new daoClass();

            }

            return factorySupportClass;
        }
    }

  public abstract class EntityServiceFactory<serviceClass, daoClass>
        where serviceClass : class, new()
        where daoClass : class
    {
        private static serviceClass factorySupportClass;

        internal static serviceClass GetInstance()
        {
            if (factorySupportClass == null)
            {
                //daoClass daoSupportClass = *how to get daoSupportClassfactory.GetInstance(); here?*
                factorySupportClass = new serviceClass(daoSupportClass);

            }

            return factorySupportClass;
        }
    }

所以他们可以像这样使用:

public static class PersonDaoFactory : Entities.EntityDaoFactory<PersonDao>
{
}

public static class PersonServiceFactory : Entities.EntityServiceFactory<PersonService, PersonDaoFactory>
{
}

以下是我遇到的问题:

  1. 不能将静态类用作泛型的类型约束,我试图将其用于EntityServiceFactory,因为没有它我不知道如何注入适当的dao。

  2. 不能让工厂派生自Generic工厂,因为我收到如下错误:

  3.   

    静态类'Persons.PersonDaoFactory'不能   来自类型   'Entities.EntityDaoFactory'。   静态类必须从object派生。

    1. 尝试用私有构造函数制作所有非静态类来解决这个问题,但后来我得到了:
    2.   

      'Persons.PersonService'必须是带有public的非抽象类型   无参数构造函数,以便将其用作参数   泛型类型或方法中的'serviceClass'   “Entities.EntityServiceFactory

      我能够读到为什么3号出现在这里,但这仍然无法解决我的问题。我让DaoFactory工作,但它只有在特定的DaoClass不需要任何依赖注入时才有效,否则错误3会再次弹出。

      有没有让这些通用工厂使用不同的方法工作,同时仍能使用DI?

      编辑----

      我能够得到这种工作,但它有一些奇怪之处。首先,我创建了一个IEntityFactory接口:

       public interface IEntityFactory<T>
          where T : class
      {
          T GetInstance();
      }
      

      然后将EntityDaoFactory更改为:

      public abstract class EntityDaoFactory<daoClass> : IEntityFactory<daoClass>
              where daoClass : class, new()
          {
              private static daoClass factorySupportClass;
      
              public daoClass GetInstance()
              {
                  if (factorySupportClass == null)
                  {
                      factorySupportClass = new daoClass();
      
                  }
      
                  return factorySupportClass;
              }
          }
      

      所以我可以传入适当的类型参数并将EntityServiceFactory更改为:

       public abstract class EntityServiceFactory<serviceClass, daoClass, daoFactoryClass>
              where serviceClass : class, new()
              where daoClass : class, new()
              where daoFactoryClass : IEntityFactory<daoClass>, new()
          {
              private static serviceClass factorySupportClass;
      
              public static serviceClass GetInstance()
              {
                  if (factorySupportClass == null)
                  {
                      daoFactoryClass daoSupportFactory = new daoFactoryClass();
                      daoClass daoSupportClass = daoSupportFactory.GetInstance();
                      factorySupportClass = new serviceClass();
      
                  }
      
                  return factorySupportClass;
              }
          }
      

      因此,对于特定的实现,例如使用Person对象,调用如下所示:

      public class PersonDaoFactory : Entities.EntityDaoFactory<PersonDao>
      {
      }
      
       public class PersonServiceFactory : Entities.EntityServiceFactory<PersonService, PersonDao, PersonDaoFactory>
      {
      }
      

      所以它现在正在运作,但奇怪的是:

      1. 您可以为EntityServiceFactory实例化一个工厂,这是必需的(据我所知,唯一的方法吗?)但是对于使用我的API的人来说,他们没有理由这样做但是他们仍然可以。

      2. 具有依赖性要求的服务和DAO现在可以在没有参数的情况下实例化,这会破坏实例化的类方法(但我必须这样做才能将它用作类型参数)。他们甚至不应该通过实例化这些对象,但他们现在可以做错了。

      3. 我刚才想到的最后一个问题是这个解决方案并没有真正处理可变数量的依赖关系。还是想知道是否有更好的方法呢?

        结论:我认为最终即使它有效,我也放弃了很多订购这个通用工厂,这不是那么灵活而且没有给我太多,所以我可能由于这些限制,在这种情况下不会使用它。

2 个答案:

答案 0 :(得分:2)

首先,您使用依赖注入 NOT Depencency injection与向通用类/方法提供类型参数无关。

错误的发生是因为您违反了C#的规则。您必须更改代码以符合它们。因此,使您的类非静态,不要使用私有构造函数。您可以使用单例实例替换静态类,并使用受保护的构造函数来避免非实现实例化。

答案 1 :(得分:0)

我知道这个问题真的很老了,但我偶然发现了它,所以我想我会给出答案。

以下编译并执行您要执行的操作:

public abstract class Entity<serviceFactory, serviceClass, daoFactory, daoClass>
    where daoFactory : Entity<serviceFactory, serviceClass, daoFactory, daoClass>.DaoFactory, new()
    where daoClass : class, new()
    where serviceFactory : Entity<serviceFactory, serviceClass, daoFactory, daoClass>.ServiceFactory, new()
    where serviceClass : class, new()
{
    public abstract class DaoFactory
    {
        private static daoClass factorySupportClass;

        internal static daoClass GetInstance()
        {
            if (factorySupportClass == null)
            {
                factorySupportClass = new daoFactory().createDao();

            }

            return factorySupportClass;
        }

        protected abstract daoClass createDao();
    }

    public abstract class ServiceFactory
    {
        private static serviceClass factorySupportClass;

        internal static serviceClass GetInstance()
        {
            if (factorySupportClass == null)
            {
                daoClass daoSupportClass = DaoFactory.GetInstance();
                factorySupportClass = new serviceFactory().createService(daoSupportClass);

            }

            return factorySupportClass;
        }
        protected abstract serviceClass createService(daoClass dao);
    }
}

现在,除非您计划在合成根目录中使用这些类型,否则我强烈建议不要执行上述解决方案,因为您的某些依赖项是隐藏的,更糟糕​​的是,它们被固定为一组有限的参数。而是尝试像this那样的更多DI /组合根友好解决方案。