Даже если вы добавите ограничение new()
, вы получите следующую ошибку
'T': невозможно предоставить аргументы при создании экземпляра типа переменной.
Вам дали неверный код.
Новое ограничение указывает, что любой аргумент типа в объявлении универсального класса должен иметь открытый конструктор без параметров. Чтобы использовать новое ограничение, тип не может быть абстрактным.
Ссылка Новое ограничение (C # Ссылка)
Другим вариантом, который следует рассмотреть, может быть использование Activator.CreateInstance (Type, Object []) .
Учитывая
public interface IContextFactory<TContext> where TContext : DbContext {
TContext Create(string connectionString);
}
Вы бы реализовали это следующим образом
public class ContextFactory<TContext> : IContextFactory<TContext>
where TContext : DbContext {
public TContext Create(string connectionString) {
var optionsBuilder = new DbContextOptionsBuilder<TContext>();
optionsBuilder.UseSqlServer(connectionString);
return (TContext)Activator.CreateInstance(typeof(TContext), optionsBuilder.Options);
}
}
Это может быть изменено в дальнейшем для разделения проблем
public class ContextFactory<TContext> : IContextFactory<TContext>
where TContext : DbContext {
public TContext Create(DbContextOptions<TContext> options) {
return (TContext)Activator.CreateInstance(typeof(TContext), options);
}
}
так, чтобы строитель стал ответственным за то, где используется фабрика.
var connection = @"....";
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlServer(connection);
//Assuming factory is `IContextFactory<BloggingContext>`
using (var context = factory.Create(optionsBuilder.Options))
{
// do stuff
}
EDIT
Завод может быть зарегистрирован как открытый дженерик в ConfigureServices
метод
services.AddSingleton(typeof(IContextFactory<>), typeof(ContextFactory<>));