Skip to content

Conversation

@alandraper
Copy link

Added GetRegisteredServices methods to expose the list of ServiceRegistrations available for a given type. This makes it possible to create a JsonContractResolver which resolves to the LightInject supplied type. Also added to mock.

@alandraper alandraper marked this pull request as ready for review September 30, 2019 15:10
@seesharper
Copy link
Owner

Hi @alandraper

I am just wondering why IServiceRegistry.AvailableServices wouldn't be sufficient here? 😀

@alandraper
Copy link
Author

It would, but then I have to look through all registrations every time, or build up a dictionary for lookups, which would duplicate the dictionary you already have.

@seesharper
Copy link
Owner

seesharper commented Sep 30, 2019

I'm just trying to understand this example
https://www.newtonsoft.com/json/help/html/DeserializeWithDependencyInjection.htm

What is actually going on here. Do you have a simpler example of what you are trying to do?

Some of the types are not even in the example 😀

@alandraper
Copy link
Author

Sure. I'm trying to create a Newtonsoft.Json.Serialization.IContractResolver which uses LightInject to create objects.

This way, when I call JsonConvert.DeserializeObject(json), it will use the LightInject container for object resolution.

Here's the implementation I'm working with now, which seems to be working.

    public class JsonContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
    {
        public JsonContractResolver(LightInject.IServiceContainer container)
        {
            this.Container = container;
        }
        private IServiceContainer Container { get; }
        protected override JsonObjectContract CreateObjectContract(Type objectType)
        {
            var services = this.Container.GetRegisteredServices(objectType);
            if (services.Any())
            {
                var resultType = services.FirstOrDefault().ImplementingType;

                JsonObjectContract contract = base.CreateObjectContract(resultType);
                contract.DefaultCreator = () => this.Container.GetInstance(objectType);
                return contract;
            }

            return base.CreateObjectContract(objectType);
        }
    }

And here's how it's used:

        JsonConvert.DefaultSettings = () => new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Objects,
            ContractResolver = new JsonContractResolver(container),
        };

@alandraper
Copy link
Author

This is also useful for implementing an easy IsRegistered(Type) method for a given service type.

Any chance of this being accepted? Or anything I can do to make it more palatable? It's hard to work from my own codebase when Umbraco references the nuget package, and running two dependency injectors on the same site seems like a recipe for trouble.

@ggjnone
Copy link

ggjnone commented Nov 25, 2022

Are there any plans to move this foward? I know its a nice to have, but for the reasons mentioned, its better to use the internal dictionary instead of creating a new one. For example in my use case I wanted to retrieve the implementing type from the handler (after being decorated it returns an instance of the decorator). And maybe this could be available on IServiceRegistry instead of IServiceFactory? Or both?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants