LightInject icon indicating copy to clipboard operation
LightInject copied to clipboard

Added GetRegisteredServices

Open alandraper opened this issue 6 years ago • 6 comments

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 avatar Sep 30 '19 15:09 alandraper

Hi @alandraper

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

seesharper avatar Sep 30 '19 21:09 seesharper

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.

alandraper avatar Sep 30 '19 21:09 alandraper

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 😀

seesharper avatar Sep 30 '19 21:09 seesharper

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

This way, when I call JsonConvert.DeserializeObject<IFoo>(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 avatar Sep 30 '19 22:09 alandraper

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.

alandraper avatar Dec 11 '19 23:12 alandraper

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?

ggjnone avatar Nov 25 '22 13:11 ggjnone