Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Sami Al Khatib
    @alsami

    hello, is there anyone here who could answer a question/provide info about best practices regarding autofac performance (for a specific case)?

    I can try. What's the case you are speaking about?

    spooky
    @spooky
    I have a factory registered like this:
            containerBuilder.Register<Func<Type, TA, TB, TC>>(c =>
            {
                var context = c.Resolve<IComponentContext>();
    
                return (type, a, b) =>
                    context.Resolve(type, new TypedParameter(typeof(TA), a), new TypedParameter(typeof(TB), b)) as TC;
            });
    that's called a lot of times and each call is ~23ms
    is there a better (faster) way do this? (because I can't really influence the number of calls :/ )
    note: there are multiple types implementing TC which is an interface
    Sami Al Khatib
    @alsami
    @spooky Currently it's InstancePerDependency(). Which will create one Instance for each requesting service. Do you need it to be in that scope?
    spooky
    @spooky
    I could use InstancePerLifetimeScope but in some cases that will be too large :/
    for web usage it would be fine, but it's also used in a windows service that's doing multiple calls
    although it being a factory... that should be fine I guess
    Sami Al Khatib
    @alsami
    Hm, no other idea here to be honest. Dealing with reflection is always time consuming, which is pretty much the case here.
    Maybe @alistairjevans has an idea
    @spooky when it's running in a windows service, does the time matter that much?
    spooky
    @spooky
    yes, it does matter unfortunately. The biggest problem it seems is the number of calls to it, but as I mentioned, I can't change that :/. I'll try to scope the factory registration and check if that improves anything. Thanks for the help
    Evan Raffel
    @evman182
    Don't know if this is something autofac supports (or the dotnet core DI container), but what I'd like is to able to have a registration that's normally transient, but for a specific "Owner", is injected within a new lifetime scope. Not sure I'm saying this right, but I'd be glad to come up with a quick code example.
    Is this possible via registration. It seems like I can do it by having the constructor parameter be Owned<>, but I'd like to do it without autofac bleeding into my other classes
    Alistair Evans
    @alistairjevans
    Its not possible at registration time I'm afraid.
    If you just want to avoid leaking Owned into the rest of your classes, you could consider wrapping Owned in your own class, so the Owned reference is limited to a single place?
    Evan Raffel
    @evman182
    Thanks. I'll see what my teammates want to do. This is just one of several possible solutions to what I'm trying to solve
    AKruimink
    @AKruimink

    Quick question
    I got a factory that creates settings for me, i would like to register it in a way that i can have them resolved
    Currently i got

    builder.RegisterType<SettingFactory>().As<ISettingFactory>().SingleInstance();
    builder.Register(x => x.Resolve<ISettingFactory>().Create<ApplicationSettings>()).As<ISetting<ApplicationSettings>>();

    That works fine, the factory itself already own a cashe and just uses it that way.
    The only thing i would like to improve is to allow for generics on ISetting

    The factory returns an ISetting<SettingType>, with the way my current code works i would need to register every settings type that exists>
    Is there anyways to make it so that i can have a depenency on ISetting<SomeType> and that Autofac uses SomeType to create the ISettings, not really caring if it's registered or not (simply said, like a generic)

    I know about RegisterGeneric, but i cant really get it to work with that either
    Sami Al Khatib
    @alsami
    @AKruimink might this be of help?
    You will need to wait for v6 though.
    If I understand your requirement correctly, this should be what you need.
    AKruimink
    @AKruimink

    @alsami Thank you for the reply, and yes i think that is what im looking for. Altho correct me if im wrong.
    My current code (that works) functions as follows.

    public SomeClass(ISettings<ApplicationSettings> appSettings)
    {
            // Constructor Code
    }

    So Autofac would have to inject a ISettings with the generic type ( in this case of type ApplicationSettings).
    My current Autofac module is setup as follows.

    builder.RegisterType<SettingFactory>().As<ISettingFactory>().SingleInstance();
    builder.Register(x => x.Resolve<ISettingFactory>().Create<ApplicationSettings>()).As<ISetting<ApplicationSettings>>();

    I register a single isntance of my SettingsFactory (single as the factory own's its own cashe system).
    Then i register the ISetting<ApplicationSettings> through the use of my Factory, the registration resolves my SettingsFactory and then uses it's Create method that creates an ISetting instance based on a given generic type

    public ISetting<TSetting> Create<TSetting>() where TSetting : new()
            {
                // creates or resolves the instance (if cashe exists)
            }

    The only thing i would like to improve is the

    builder.Register(x => x.Resolve<ISettingFactory>().Create<ApplicationSettings>()).As<ISetting<ApplicationSettings>>();

    That the ApplicationSettings could be used as a generic, so i don't have to register every single possible setting's type, but can just say, i want a ISetting of wat ever type and let my own factory deal with the creation.

    If i understand that PR correctly that generic usage would be possible in v6?

    Dima Enns
    @Yeah69
    Init-members on properties (C#9.0) could be an opportunity for elegant property injection. Are there any plans to utilize this new language feature in Autofac?
    Dima Enns
    @Yeah69

    I have tried it myself with the .Net 5.0 preview:

    using System;
    using System.Linq;
    
    internal class Test
    {
        public int TestProp { private get; init;  }
    
        public override string ToString()
        {
            return TestProp.ToString();
        }
    
        public static void Main()
        {
            // Sanity check
            Console.WriteLine("Hello World!"); // Hello World!
    
            var test = new Test { TestProp = 69 };
    
            // Check normal way
            Console.WriteLine($"Hello {test}!"); // Hello 69!
    
            Type type = typeof(Test);
            var propertyInfo = type.GetProperties().First();
            var test2 = Activator.CreateInstance<Test>();
    
            propertyInfo.SetValue(test2, 23);
    
            // Check reflection way
            Console.WriteLine($"Hello {test2}!"); // Hello 23!
        }
    }

    Seems like reflection doesn't distinguish between set and init.

    Sami Al Khatib
    @alsami

    Init-members on properties (C#9.0) could be an opportunity for elegant property injection. Are there any plans to utilize this new language feature in Autofac?

    Currently there are no plans for init-properties and C# 9 features. Feel free to open a feature-request.
    https://github.com/autofac/Autofac/issues/new?assignees=&labels=&template=feature_request.md&title=

    Nirajan Kharal
    @nkharal
    Having issue with using Autofac with IHostBuilder. I am able to resolve service after builder.Build(). However, when i run application with
    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .ConfigureServices((hostContext, services) =>
    {
    services.AddHostedService<SomeService>();
    });
    I get "An exception was thrown while activating λ:Microsoft.Extensions.Hosting.IHostedService[] . SomeService" . DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder. Any help will be appreciated?
    Sami Al Khatib
    @alsami
    The stack trace should tell you which class can not be resolved. If you post the whole stack trace I might be able to help you.
    What dependencies does someservice have? Did you register all of them?
    Nirajan Kharal
    @nkharal
    Hi ... I am able to resolve them all if I don't use IHostBuilder so i feel i am missing some configuration. Autofac is working fine when i use it with topself. When trying to migrate to WorkerService is where I get problem.
    Sami Al Khatib
    @alsami
    Would be good if you could provide a sample or the whole stack trace. In general the way you use it seems to be fine.
    Nirajan Kharal
    @nkharal
    I have direct messaged you the stack trace
    Nirajan Kharal
    @nkharal
    Thanks @alsami for all your help
    Jerome Haltom
    @wasabii
    Hey friends. I'm trying to figure out the best way to add a generic registration to a IComponentRegistryBuilder (from a callback). The RegisterGeneric extension method is only available on teh ContainerBuilder, it seems. And all the OpenGeneric stuff is internal. Any ideas?
    Jerome Haltom
    @wasabii
    Well, so, I got it to work by passing the ContainerBuilder through, and using reflection to access RegistrationBuilder and OpenGenericRegistrationSource. But that's all lame.
    Jerome Haltom
    @wasabii
    Also, how the heck are you supposed to manually invoke an Activator now to create an instance?
    Evertyhing was replaced with ServiceRegistration, instead of the RegistrationAccessor delegates.... and Activator on the registration no longer just has an activate method.
    Alex Meyer-Gleaves
    @alexmg
    @wasabii I assume you a referring to an Autofac build callback? Are you resolving a service after container build that is providing the information for the open generic registrations? If the open generic registrations are for a known open generic type you may be able to create your own IRegistrationSource for them that is updated after build with additional known concrete types before they are resolved.
    Alex Meyer-Gleaves
    @alexmg
    Is it the open generic type you don't know ahead of time? The same approach would still work assuming the scenarios don't invole some of the more complex edge cases covered in the OpenGenericRegistrationSource.
    If you can provide some more detail we might be able to figure something out for you that doesn't involve falling back to reflection based hacks. It's never nice to have that kind of ticking time bomb lurking around in your code. 🙂
    Jerome Haltom
    @wasabii
    @alexmg Yeah, working on my MS DI adaptor. Need to handle generics in it. But I do all my work in a BuildCallback. At which time I only have a IContainerRegistryBuilder.
    Before 6 I had copied the entire OpenGeneric hierarchy of code into my own, and just added a Source. That worked. But it was ugly. What I've done now is used reflection to create a RegistrationBuilder and a OpenGenericRegistrationSOurce. Also, not great.
    Jerome Haltom
    @wasabii
    (I have my own MS DI Populate method, that supports some of the more esoteric users of MS DI, that actually try to REMOVE things from ServiceCollection).
    markelli
    @markelli
    When I create a LifetimeScope through dependency in the constructor like MyViewModel(ILifetimeScope scope) then I should be calling dispose on that scope object in the dispose of MyViewModel right? And that will result in disposing of all the objects resolved using that scope?
    Alex Meyer-Gleaves
    @alexmg

    @markelli The constructor of MyViewModel is not creating the ILifetimeScope instance, it is receiving a reference to the ILifetimeScope that it is being created in. Because the view model did not create the lifetime scope it should not be disposing it. The lifetime scope should be disposed by the thing that created it.

    I would recommend having a read of this blog post from Nick to get a better understanding of lifetime scopes. It written some time ago but remains entirely relevant.

    https://nblumhardt.com/2011/01/an-autofac-lifetime-primer/

    @wasabii Is the adaptor open source or something from your work? How does it fit in with the existing Microsoft abstraction for DI?
    markelli
    @markelli

    @alexmg If I'm creating that MyViewModel via autofac though then the only object that by default knows about that instance of ILifetimeScope would be the MyViewModel no? So where else would I dispose of it?

    In this specific case I have another object like MyFirstViewModel which has a call to scope in it to scope.Resolve<MyViewModel>() but the only way it would know about the scope created for MyViewModel is if that were then exposed as a property or something of that nature.

    Alex Meyer-Gleaves
    @alexmg
    Is the scope you referred to in MyFirstViewModel a new child lifetime scope? If it is not and MyViewModel is resolved from the root lifetime scope disposing it would not be a good thing. You might need to provide some more example code so we can better understand your scenario.