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

本文关键字:工厂 不可能 依赖 注入 | 更新日期: 2023-09-27 18:16:25

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

通常我的service和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. 不能让工厂从通用工厂派生,因为我得到一个错误:

静态类Persons。PersonDaoFactory"不能源自type"Entities.EntityDaoFactory"。静态类必须从object派生。

  1. 试着让他们所有的非静态类与私有构造函数来解决这个问题,但后来我得到:

的人。PersonService必须是具有public的非抽象类型无参数构造函数,以便将其用作参数泛型类型或方法中的'serviceClass'的实体。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现在可以在没有参数的情况下实例化,这将破坏实例化的类方法(但我必须这样做才能将其用作类型参数)。他们甚至不应该实例化这些对象,但他们现在可以这样做,并且做得不正确。

我刚刚想到的最后一个问题是,这个解决方案并不能很好地处理依赖关系的可变数量。仍然想知道是否有更好的方法?

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

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

首先,您不是使用依赖注入。依赖注入与向泛型类/方法提供类型参数无关。

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

我知道这个问题很老了,但是我无意中发现了,所以我想我应该给出一个答案。

下面的代码编译并执行您想要执行的操作:

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

现在,除非您计划在组合根中使用这些类型,否则我强烈建议不要使用上述解决方案,因为您的一些依赖项是隐藏的,更糟的是,它们被固定到一组有限的参数中。相反,可以尝试这样做,以获得更适合DI/组合根的解决方案。