JasperFx / lamar

Fast Inversion of Control Tool and Successor to StructureMap
https://jasperfx.github.io/lamar
MIT License
571 stars 119 forks source link

Generic Instance Builder alternative from StructureMap #308

Closed ivansorokinf closed 2 years ago

ivansorokinf commented 2 years ago

Hello! We are moving from StructureMap to Lamar and can't find a proper way to migrate piece of code similar to Generic Instance Builder Example 2 from http://structuremap.github.io/generics/#sec5, we have it implemented exactly as in this guide. I couldn't find a guide about this in Lamar and my different recreation attempts failed due to huge differences in syntax. Is this double instance approach still viable in Lamar and how to achieve it if so? Thanks!

I tried to change code like this (had to change Instance to LambdaInstane because Instance forces me to overload some methods I don't know how to overload correctly). I am getting "cannot be cast" exceptions with this code (also with Instance and overriden methods that throw NotImplemented exceptions)

registry For(typeof(IMongoCollection<>)).Use(typeof(IMongoCollectionInstanceFactory)).Singleton();

instance factory

class IMongoCollectionInstanceFactory : LambdaInstance
    {
        public override Instance CloseType(Type serviceType, Type[] templateTypes)
        {
            var instanceType = typeof (IMongoCollectionInstance<>).MakeGenericType(templateTypes);
            return Activator.CreateInstance(instanceType) as Instance;
        }

        public IMongoCollectionInstanceFactory(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime lifetime) : base(serviceType, factory, lifetime)
        {
        }
    }

collection instance

    class IMongoCollectionInstance<T> : LambdaInstance<IServiceProvider, IMongoCollection<T>>
    {
        public IMongoCollectionInstance() : base(typeof(IMongoCollection<T>),
                                                 c => c.GetService<MongoCollectionFactory>().CreateIMongoCollection<T>(),
                                                 ServiceLifetime.Singleton)
        {
        }
    }
ivansorokinf commented 2 years ago

Okay, it seems my previous registration is wrong and I have to use something like this instead of type argument. I managed to get my code working now. But I am still curious is it the best way to achieve my goal.

For(typeof(IMongoCollection<>)).Use(new IMongoCollectionInstanceFactory(typeof(IMongoCollection<>),
                                                                                    provider => provider.GetService<IMongoCollectionInstanceFactory>(),
                                                                                    ServiceLifetime.Singleton));