Для полноты, вот пример того, как сделать это с использованием незарегистрированного разрешения типа:
container.ResolveUnregisteredType += (s, e) =>
{
var serviceType = e.UnregisteredServiceType;
if (serviceType.IsGenericType &&
serviceType.GetGenericTypeDefinition() == typeof(IDatabaseMapper<>))
{
Type argument = serviceType.GetGenericArguments()[0];
var closedDatabaseMapperType = typeof(DatabaseMapper<,>)
.MakeGenericType(argument, typeof(OracleException));
var registration =
container.GetRegistration(closedDatabaseMapperType, true);
e.Register(registration.BuildExpression());
}
};
Событие ResolveUnregisteredType
будет вызываться контейнером всякий раз, когда запрашивается тип, который не зарегистрирован.Это дает вам последний шанс зарегистрировать этот тип.Поставляемый UnregisteredTypeEventArgs
содержит две перегрузки метода Register
, которые позволяют вам зарегистрировать этот тип (используя Func<T>
или Expression
).
Приведенный выше код проверяет, запрашивается ли запрошенная службатипом является IDatabaseMapper<T>
, и если это так, он создает DatabaseMapper<T, OracleExpression>
, где T
заменяется фактическим типом типа службы.Используя этот тип, регистрация для этого типа запрашивается из контейнера.Используя метод BuildExpression
этого объекта регистрации, мы можем построить дерево выражений, которое описывает создание нового экземпляра этого DatabaseMapper
.Это выражение с идентификатором зарегистрировано с использованием метода e.Register
, который фактически сопоставляет IDatabaseMapper<T>
с созданием DatabaseMapper<T, OracleException>
.
. ВАЖНО: я считаю, что использование незарегистрированного разрешения типов следует использовать только как запасной вариант, поскольку часто есть более простые способы решения вашей проблемы (например, тот, который я показал в моем другом ответе), но разрешение незарегистрированного типа может быть полезно в определенных расширенных сценариях (например, когда DatabaseMapper<T, TException>
запечатан).