2012-01-24 1 views
0

Есть ли способ получить общий завод, когда класс, который он возвращает, требует параметра в конструкторе? Все мои заводы выглядят следующим образом:Возможно ли создать общий завод с конструктором с параметрами с помощью Activator.CreateInstance()?

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

Однако, это, конечно, не будет работать, потому что я не могу использовать класс, который не имеет конструктора без параметров, как общий параметр, но я чувствую, что я рядом. Я думал о передаче класса Service как GetService(Type serviceClassType), но тогда я не могу объявить тип возвращаемого метода и должен был бы его использовать, когда я его назову, чего я хочу избежать.

Есть ли другой подход? Возможно ли это?

+0

@vcsjones Можете ли вы уточнить, что вы имеете в виду? Обычно я использую свои заводы для выполнения DIing (так как вы можете видеть, что для обслуживания нужен репозиторий, и мой завод позаботится об этом). Разве это не потребовало бы конкретной реализации для каждой услуги? Также, пожалуйста, напишите в разделе ответов для репутации! – SventoryMang

+0

Извините, я неправильно понял. – vcsjones

+0

@vcsjones вы были правы, но удаление new() было выполнено. Поэтому, пожалуйста, пишите в разделе ответов! – SventoryMang

ответ

3

Вы могли бы сделать что-то вроде этого, и принять оба типа в качестве параметров типа:

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 разрешить это, и современный контейнер будет разрешать зависимости зависимостей.

+0

Спасибо, я подумал о первом методе, однако соглашение всегда есть, и я хотел, чтобы вызов метода был как можно более простым. Все еще немного смущенно о вашем комментарии к контейнеру DI, поскольку текущий завод уже использует инъекцию зависимостей, как указано в вашей ссылке? Можете ли вы сделать быстрый пример, даже в псевдокоде будет полезно? – SventoryMang

Смежные вопросы