【问题标题】:Is it possible to create a generic factory with constructor with parameters using Activator.CreateInstance()?是否可以使用 Activator.CreateInstance() 使用带有参数的构造函数创建通用工厂?
【发布时间】:2012-01-24 20:42:40
【问题描述】:

当它返回的类需要构造函数中的参数时,有什么方法可以实现泛型工厂?我所有的工厂都是这样的:

public static class UserServiceFactory
{
    public static UserService GetService()
    {
        UserRepository userRepository = new UserRepository();
        return new UserService(userRepository);
    }

}

我尝试过这样的事情:

 public static TServiceClass GetService<TServiceClass>()
        where TServiceClass : class, new()
    {
        TServiceClass serviceClass = null;

        string repositoryName = typeof (TServiceClass).ToString().Replace("Service", "Repository");
        Type type = Type.GetType(repositoryName);

        if (type != null)
        {
            object repository = Activator.CreateInstance(type);
            serviceClass =  (TServiceClass)Activator.CreateInstance(typeof (TServiceClass), new[]{repository});
        }

        return serviceClass;
    }

但是,这当然行不通,因为我不能使用没有无参数构造函数的类作为泛型参数,但我觉得我很接近。我考虑过像 GetService(Type serviceClassType) 这样传递 Service 类,但是我无法声明该方法的返回类型,并且在调用它时必须强制转换它,我想避免这种情况。

还有其他方法吗?这甚至可能吗?

【问题讨论】:

  • @vcsjones 你能详细说明你的意思吗?通常,我使用我的工厂进行 DIing(如您所见,该服务需要一个存储库,而我的工厂负责处理)。这不是再次需要每个服务的具体实现吗?也请在代表的答案部分发帖!
  • @vcsjones 你是对的,但删除 new() 有效。所以请先生在答案部分发帖!

标签: c# generics factory-pattern


【解决方案1】:

您可以这样做,并将两种类型都作为类型参数:

public static TService GetService<TRepository, TService>() where TRepository:new()
{
    var repository = new TRepository();
    return (TService)Activator.CreateInstance(typeof(TService), repository);
}

或者,如果您想依赖服务和存储库同名的约定(仅用于说明):

public static TService GetService<TService>()
{
    var repositoryName = String.Concat(typeof(TService).Namespace, Type.Delimiter, typeof(TService).Name.Replace("Service", "Repository"));
    object repository = Activator.CreateInstance(Type.GetType(repositoryName));
    return (TService)Activator.CreateInstance(typeof(TService), repository);
}

这感觉不明显也不直观,也许有更好、更强大的解决方案可用。

也许使用inversion of control container 是一种更好的方法。

使用容器,我只需解析UserService 并让容器注入适当的存储库。如果 UserService 是其他东西的依赖,让 DI 容器解决它,现代容器将解决依赖关系。

【讨论】:

  • 谢谢,我确实想到了第一种方法,但是约定总是存在的,我想让方法调用尽可能简单。由于当前工厂已经在使用链接中提到的依赖注入,您的 DI 容器注释仍然有点困惑?你能做一个简单的例子吗,即使是伪代码也会有帮助?
猜你喜欢
  • 2014-11-14
  • 2013-09-23
  • 1970-01-01
  • 2021-11-15
  • 2018-10-01
  • 2013-06-16
  • 2020-08-16
  • 2021-12-15
  • 1970-01-01
相关资源
最近更新 更多