Хорошо, еще несколько вариантов, которые помогут вам улучшить ваш код.Предполагая следующую модель:
public class DataBaseLayer
{
private readonly string _connectionString;
private readonly string _userName;
private readonly ILogger _logger;
private readonly ITypeMapper _mapper;
public DataBaseLayer(
string connectionString,
string userName,
ILogger logger,
ITypeMapper mapper)
{
_connectionString = connectionString;
_userName = userName;
_logger = logger;
_mapper = mapper;
}
}
public interface ITypeMapper
{
}
public class TypeMapper : ITypeMapper
{
}
public interface ILogger
{
}
public class ConsoleLogger : ILogger
{
}
public class FileLogger : ILogger
{
}
1) Уменьшите количество магических строк в коде
Первым делом попытайтесь уменьшить количество магических строк в вашем коде, например:"connectionString"
и "userName"
:
container.RegisterInstance(typeof(string), "userName", "my username");
container.RegisterInstance(typeof(string), "connectionString", "my connection string");
Таким образом, вместо повторения подобных вещей по всему коду ...
new InjectionConstructor(
new ResolvedParameter<string>("connectionString"),
new ResolvedParameter<string>("userName"),
/* .... */
);
Вы можете создавать свои собственные классы параметров, которые выводятс ResolveParameter
:
public class UsernameParameter : ResolvedParameter<string>
{
public static UsernameParameter Instance => new UsernameParameter();
public static string ParameterName => "userName";
private UsernameParameter() : base(ParameterName)
{
}
}
public class ConnectionStringParameter : ResolvedParameter<string>
{
public static ConnectionStringParameter Instance => new ConnectionStringParameter();
public static string ParameterName => "connectionString";
private ConnectionStringParameter() : base(ParameterName)
{
}
}
Зачем беспокоиться?Таким образом, вам не нужно повторять строки "connectionString"
и "userName"
, и если вам нужно изменить их, все, что вам нужно сделать, это отредактировать свойство ParameterName
в соответствующем классе.
Регистрация строк с использованием ConnectionStringParameter
и UsernameParameter
:
container.RegisterInstance(typeof(string), UsernameParameter.ParameterName, "my username");
container.RegisterInstance(typeof(string), ConnectionStringParameter.ParameterName, "my connection string");
Использование параметров:
new InjectionConstructor(
ConnectionStringParameter.Instance,
UsernameParameter.Instance,
/* .... */
);
2) Использовать методы расширения или фабрикичтобы удалить дублирование кода
Например, предположим, что вы хотите зарегистрировать различные экземпляры DataBaseLayer.Единственная разница между этими экземплярами - тип используемого регистратора.Регистрация экземпляров ILogger
:
container.RegisterType<ILogger, FileLogger>("file");
container.RegisterType<ILogger, ConsoleLogger>("console");
Регистрация экземпляров DataBaseLayer
с использованием метода расширения:
container.RegisterDataBaseLayer(instanceName: "fileDatabaseLayer", loggerType: "file");
container.RegisterDataBaseLayer(instanceName: "consoleDatabaseLayer", loggerType: "console");
Реализация метода расширения RegisterDataBaseLayer
:
public static class UnityContainerExtensions
{
public static IUnityContainer RegisterDataBaseLayer(
this IUnityContainer container,
string instanceName,
string loggerType)
{
container.RegisterType<DataBaseLayer>(
instanceName,
new InjectionConstructor(
ConnectionStringParameter.Instance,
UsernameParameter.Instance,
new ResolvedParameter<ILogger>(loggerType),
new ResolvedParameter<ITypeMapper>()
)
);
return container;
}
}
3) Если возможно, сгруппируйте параметры
Вместо ....
public class FooService
{
public FooService(string userName, string password)
{
// ...
}
}
Do:
public class FooService
{
public FooService(Credentials credentials)
{
// ...
}
}
public class Credentials
{
public string Username { get; set; }
public string Password { get; set; }
}
Это будетупростите свою жизнь при регистрации типов с использованием контейнера IoC и сократите код Bootstrapper.
4) Создайте модульные тесты для своего контейнера Bootstrapper / IoC
Это чрезвычайно важно и может избавить вас от головной боли,Если вы чувствуете, что ваш код хрупкий и может произойти сбой, если / когда класс будет изменен (например, при изменении или добавлении нового конструктора), то вам следует добавить несколько тестов для каждого зарегистрированного типа и / или именованного экземпляра.
Вы должны по крайней мере проверить, может ли контейнер разрешить конкретный экземпляр, без выдачи исключений.