I'm trying to inject a service to my controllers but I want to inject a different instance of my service depending of several parameters. Actually for this part it's working, I'm able to do it.
What I want is to load a specific instance of IRepository<Database>
based on some configuration we get from a configuration file and respecting the DRY rule (don't repeat yourself).
I have these 2 classes:
public abstract class FooServicesProvider
{
public Func<IServiceProvider, IRepository<Database>> DatabaseRepository = provider =>
{
return null;
};
}
public class FooFileSystemServicesProvider : FooServicesProvider
{
public new Func<IServiceProvider, IRepository<Database>> DatabaseRepository = provider =>
{
//Specific code determining which database to use and create a new one if needed
//our databases are FOLDERS containing some files
//knowing how chosenDb.FullName is set is not important here
//[...]
var databaseRepository = new DatabaseFileSystemRepository(chosenDb.FullName);
databaseRepository.testProperty = "Foo value";
return databaseRepository;
};
}
Notice the new keyword used to redefine the code of my Func. This is the best way I found because of the Func delegate, I'm very limited, I can't use it in an Interface neither override it.
Now in my ConfigureServices method in Startup.cs I have this code
var fakeConfiguration = "File";
FooServicesProvider servicesProvider = null;
if(fakeConfiguration == "File")
{
servicesProvider = new FooFileSystemServicesProvider();
}
else
{
servicesProvider = new AnotherFooServicesProvider();
}
//Here is the tricky part
//This should call FooFileSystemServicesProvider.DatabaseRepository because of the "new" keyword, but it's NOT
services.AddScoped<IRepository<Database>>(servicesProvider.DatabaseRepository);
My problem is that the new keyword is ignored at runtime and the executed Func is the one declared in my base class instead of the derived one.
If I do this it's working
services.AddScoped<IRepository<Database>>((servicesProvider as FooFileSystemServicesProvider).DatabaseRepository);
But I don't want to cast it as I can't know of which type my servicesProvider will finally be.
I've tried to get the type of my servicesProvider and cast it with its own type but I get compiler error because a Type variable and a Class are different.
So how can I get the good Func executed at runtime? Thanks
Ok so I finally managed to do what I want, it was actually not that hard, my main problem was to handle the fact that my Func was not a method but a delegate. I'm not used to deal with this variable type.
My code in Startup.cs remains unchanged but here is the new code of my custom ServicesProvider
public abstract class FooServicesProvider
{
public Func<IServiceProvider, IRepository<Database>> DatabaseRepository { get; protected set; }
}
public class FooFileSystemServicesProvider : FooServicesProvider
{
public FooFileSystemServicesProvider()
{
base.DatabaseRepository = GetDatabaseRepository;
}
private DatabaseFileSystemRepository GetDatabaseRepository(IServiceProvider serviceProvider)
{
//Specific code determining which database to use and create a new one if needed
//our databases are FOLDERS containing some files
//knowing how chosenDb.FullName is set is not important here
//[...]
var databaseRepository = new DatabaseFileSystemRepository(chosenDb.FullName);
databaseRepository.testProperty = "Foo value";
return databaseRepository;
}
}
Just in case people are wondering: DatabaseFileSystemRepository
is a class that implements the interface IRepository<Database>>
If anyone comes up with a different solution, I'm very curious to know it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.