How to resolve dependency in dependency register time in Autofac - autofac

earlier I used Microsoft unity IOC. Unity container has RegisterType & Resolve method. So I able to resolve same interface with multiple implementation. but latest autofac (var builder = new ContainerBuilder();) builder hasn't resolve() method and we can't manually build (builder.Build();).
Anyone has any idea, how to convert below code base to autofac or how to use resolve method with dependency registration.
container.RegisterType<IQueryManager, FirstManager>(new TypedParameter(typeof(GeneralEnumerations.DatabaseType), GeneralEnumerations.DatabaseType.First));
container.RegisterType<IQueryManager, SecondManager>(new TypedParameter(typeof(GeneralEnumerations.DatabaseType), GeneralEnumerations.DatabaseType.Two));
container.RegisterType<IQueryManager, ThirdManager>(new TypedParameter(typeof(GeneralEnumerations.DatabaseType), GeneralEnumerations.DatabaseType.Three));
Func<DatabaseType, IQueryManager> priceFactory = (databaseType) => container.Resolve<IQueryManager>(databaseType.ToString());
container.RegisterInstance<IQueryManagerFactory<IQueryManager>>(new QueryManagerFactory<IQueryManager>(priceFactory));
I try this but not working. any suggestion how to solve this with"builder.RegisterInstance".
builder.Register<IQueryManagerFactory<IQueryManager>>(container => new QueryManagerFactory<IQueryManager>(databaseType =>
container.Resolve<IQueryManager>(new TypedParameter(typeof(GeneralEnumerations.DatabaseType), databaseType))
));

Related

Choose dependency for injection using Kiwi in Flutter

I have the following code:
KiwiContainer()
..registerFactory((c) => GetOrderListOfItemsUseCase(
repository: c<ShopRepository>()))
The problem here is that the GetOrderListOfItemsUseCase requires an instance of IProfileRepository which the ShopProfileRepository extends from.
NOTE: IProfleRepository is extended by IUserProfileRepository and IShopProfileRepository.
UPDATE: I have the following factories:
..registerFactory<IShopRepository>((c) => c<ShopRepository>())
..registerFactory<IUserProfileRepository>((c) => c<UserProfileRepository>())
The thing is that I want to dynamically inject the proper dependency for GetUserLocationsUseCase.
..registerFactory(
(c) => GetUserLocationsUseCase(repository: c<IProfileRepository>()))
how can I inject in the code the proper subtype of IProfileRepository whether it IShopRepository or IUserProfileRepository?
If you want to dinamically inject either UserProfileRepository or ShopProfileRepository you should register the one you are going to use via its supertype.
KiwiContainer()
..registerFactory<IProfleRepository>((c) => ShopProfileRepository())
..registerFactory((c) => GetOrderListOfItemsUseCase(
repository: c<IProfleRepository>()))
And obtain it via its supertype too, like in the snippet.

Is it possible to use Autofac somehow within Unity3d?

I am using Unity3d 2018.1.0f3 which is using .net 4.6x and has netstandard 2.0. Does anyone know if its possible to get Autofac working within Unity? Currently, I get an error saying that it unloaded the assemblies due to possible runtime issues.
Thanks,
MH
I have no idea about the other stuff, and I use an older version of it, but I use AutoFac (3.5.2) with Unity with no issues at all. I think it needs slightly different setup for unity but not really sure. but I have an editor window system that uses ScriptableObjects for databases and seperate pages for different item types, and use autofac to inject the databases, and find all the sub pages and auto load them.
this is how I do it if this helps:
private ISWeaponDatabase weaponDb;
private ISQualityDatabase qualityDb;
private ISArmorDatabase armorDb;
private int currentTab;
private ContainerBuilder builder;
private BasePage[] pages;
DatabaseConfig dbConfig = Resources.Load<DatabaseConfig>("DatabaseConfig");
if (dbConfig == null) return;
if (weaponDb == null) weaponDb = ISWeaponDatabase.GetDatase<ISWeaponDatabase>(dbConfig.DataFolder, dbConfig.WeaponDatabase.DatabaseFile);
if (qualityDb == null) qualityDb = ISWeaponDatabase.GetDatase<ISQualityDatabase>(dbConfig.DataFolder, dbConfig.QualityDatabase.DatabaseFile);
if (armorDb == null) armorDb = ISArmorDatabase.GetDatase<ISArmorDatabase>(dbConfig.DataFolder, dbConfig.ArmorDatabase.DatabaseFile);
builder = new ContainerBuilder();
builder.RegisterInstance(weaponDb).As<ISWeaponDatabase>();
builder.RegisterInstance(armorDb).As<ISArmorDatabase>();
builder.RegisterInstance(qualityDb).As<ISQualityDatabase>();
builder.RegisterAssemblyTypes(Assembly.GetAssembly(GetType())).Where(t => t.Name.EndsWith("EditorPage")).As<BasePage>().SingleInstance();
IContainer container = builder.Build();
pages = container.Resolve<IEnumerable<BasePage>>().ToArray();
Yes, it is possible, would be nice to know what you tried until now, but basically, you'll import it as you'd import every other 3rd party library.
I assume you are on an up-to-date Windows Machine and you are using VS because you didn't give us any information on that.
Fire up your NuGet PM in VS (Tools > NuGet Package Manager > Console)
Command: Install-Package Autofac -Version 4.8.1
Or your preferred way to get a NuGet package https://www.nuget.org/packages/Autofac/ (VS is of course also working)
Now you should have a package in /Packages/Autofac.4.8.1/lib/net45
Copy the DLL over to your assets/lib folder (or wherever you want to have it)
If you go back to Unity it will load Autofac now
Now you can go to any class you have and type "using Autofac" and get started.

What is InstancePerLifetimeScope in Autofac?

Can someone please explain in plain English what the lines of code where I put the question marks do? Or maybe point me to an article that puts light on this. This code is for registering dependencies in an autofac container
var builder = new Autofac.ContainerBuilder();
builder.Register<NHibernateInstance>(c =>
new NHibernateInstance(ConnString, false))
.InstancePerDependency();//?????
builder.Register(c => c.Resolve<NHibernateInstance>()
.GetFactory().OpenSession())
.As<ISession>()
.InstancePerLifetimeScope(); //-----?????
This is a dependency injection container. The Autofac.ContainerBuilder gets a new container, or registrar you might say.
The builder.Register<NHibernateInstance> is stating that when constructing an NHibernateInstance during the recovery phase (i.e. getting an instance out of the container) this is how it should be built.
The last line is indicating that when resolving an NHibernateInstance the OpenSession method should be called once per the lifetime of the object.

Make use of AllTypes.FromAssemblyContaining() / UsingFactoryMethod()

I am registering many repositories which are located in the same assembly by using the following code:
IoCContainer.Register(AllTypes.FromAssemblyContaining<RepositoryOne>).BasedOn(typeof(IRepository<>)).WithService.AllInterfaces().Configure(c => c.LifeStyle.Singleton));
Because I want to have influence on the creation of these repositories, I am trying to use UsingFactoryMethod() with it. Using this method is simple when I register every repository separately like
IoCContainer.Register(Component.For<IRepositoryOne>().ImplementedBy<RepositoryOne>().LifeStyle.Singleton.UsingFactoryMethod(() => Factory.New<RepositoryOne>()));
...
IoCContainer.Register(Component.For<IRepositoryN>().ImplementedBy<RepositoryN>().LifeStyle.Singleton.UsingFactoryMethod(() => Factory.New<RepositoryN>()));
But how can I use UsingFactoryMethod() together with the code from the first example?
TIA
You have to use a bit of reflection to use it, since you don't have the exact type of the object you'd be resolving.
var factoryMethod = typeof(Factory).GetMethod("New", BindingFlags.Static|BindingFlags.Public);
container.Register(
AllTypes.FromAssemblyContaining<RepositoryOne>)
.BasedOn(typeof(IRepository<>))
.WithService.AllInterfaces()
.Configure(x => x.UsingFactoryMethod((k, c) => factoryMethod.MakeGenericMethod(c.RequestedType).Invoke(null, null)));

Autofac parameter passing

I've been trying to integrate the latest version of autofac (1.3.3.54), and I'm running into the following problem.
The recommended way of consuming parameters in the Register callback, per the Google code wiki for the project is as follows:
builder.Register((c, p) => new Foo(p.Get("arg1")));
However this won't compile with the mentioned version of the autofac code. I looked through the source and I see that p is an IEnumerable (ComponentActivatorWithParameters). Is the code out of date with respect to the documentation?
It appears that the code has changed and the documentation on the Wiki has not been updated. The "Get" method is now "Named" and the "Parameter" class is now "NamedParameter". See the following example:
var builder = new ContainerBuilder();
builder.Register((c, p) => new Person(p.Named<string>("name")));
using (var container = builder.Build())
{
var person = container.Resolve<Person>(new NamedParameter("name", "Fred"));
}
Hopefully someone can update the documentation soon.
I've attached freshly built documentation for AutoFac 1.3 to AutoFac issue #121. I hope they'll resume posting official 1.3 documentation at least until they retire the 1.3 branch and, with it, support for .NET 2.0.