Grace icon indicating copy to clipboard operation
Grace copied to clipboard

Error thrown on method Import with key

Open XanNava opened this issue 2 years ago • 5 comments

The fallowing is the coding I am using (note the different commented out elements to test behaviors are working properly in other ways).

// See https://aka.ms/new-console-template for more information

using Grace.DependencyInjection;
using Grace.DependencyInjection.Attributes;

DependencyInjectionContainer container = new DependencyInjectionContainer((c) => {
	c.AutoRegisterUnknown = true;
	c.Trace = (s => {
		Console.WriteLine(s);
	});
});

container.Configure((c) => {
	c.Export<Service>().AsKeyed<IService>("ServiceM");

	c.Export<ServiceAlt>().AsKeyed<IService>("ServiceA");

	// Will default to this if a key import fails.
	// Allows for the default [import()].
	//c.Export<Service>().As<IService>();
});

var scope = container.BeginLifetimeScope("RootScope");

var alt = container.Locate<IService>(withKey: "ServiceA");
var service = container.Locate<ServiceMain>();

Console.WriteLine(service.Service.GetString());

interface IService {
	string GetString();
}

class Service : IService {
	public virtual string GetString() {
		return "Service";
	}
}

class ServiceAlt : IService {
	public string GetString() {
		return "Service AlternativeService";
	}
}

class ServiceMain {
	// Works.
	//[Import(Key = "ServiceA")]
	public IService Service { get; set; }

	// Works with export "c.Export<Service>().As<IService>();"
	//[Import()]
	
	// Throws error that type reference in Grace is null.
	[Import(Key = "ServiceA")]
	public void Recieve(IService service) {
		Console.WriteLine("Import through method");
		Service = service;
	}
}

The above throws the fallowing error.

Unhandled exception. Grace.DependencyInjection.Exceptions.LocateException: Could not locate Type IService
1 Importing ServiceMain
2 Importing IService  for method Recieve parameter service

   at Grace.DependencyInjection.Impl.InjectionContextValueProvider.GetValueFromInjectionContext[T](IExportLocatorScope locator, StaticInjectionContext staticContext, Object key, IInjectionContext dataProvider, Object defaultValue, Boolean useDefault, Boolean isRequired)
   at lambda_method2(Closure , IExportLocatorScope , IDisposalScope , IInjectionContext )
   at Grace.DependencyInjection.Impl.ActivationStrategyDelegateCache.FallbackExecution(ImmutableHashTree`2 currentNode, Type type, IExportLocatorScope scope, Boolean allowNull, IInjectionContext context)
   at Grace.DependencyInjection.Impl.ActivationStrategyDelegateCache.ExecuteActivationStrategyDelegate(Type type, IExportLocatorScope scope)
   at Grace.DependencyInjection.Impl.BaseExportLocatorScope.Locate[T]()
   [My code url]/Program.cs:line 25

Grace version 8.0.0-Beta822

XanNava avatar Nov 05 '22 12:11 XanNava

So I made a fork of the repo and it looks like the key isn't getting passed into the fallowing method it is just null. InjectionContextValueProvider.GetValueFromInjectionContext<T>(....)

If I set the key manually key = (object)"ServiceA"; the path to call GetValueFromExtraDataProvider<T>(...) is taken, but there is still an issue that the fallowing two calls in the method return null. InjectionContext.GetExtraData(object key) <-- Method _extraDataProperties.GetValueOrDefault(stringKey) <-- Call in method _extraDataValues.GetValueOrDefault(key)<-- Call in method

XanNava avatar Nov 06 '22 01:11 XanNava

https://github.com/XanNava/GraceTests You can see my tests by cloning the above fork. Note I removed .net FrameWork 4.5 from the build target just to get it running on my pc. Run GraceTests.ConsoleApp for Method logging.

XanNava avatar Nov 06 '22 02:11 XanNava

The IExportLocatorScope locator argument for InjectionContextValueProvider.GetValueFromInjectionContext<T>(....) Is correct, and can be used to locate the service by the key.

XanNava avatar Nov 06 '22 02:11 XanNava

Still not sure why the key isn't being passed in, but the call GetValueFromExtraDataProvider<T>(key, currentLocator, out value) seems to not be working properly and where the method call ends and value is still null if there is a key value. I have narrowed the issue down to seemingly the two fallowing things.

  1. Key not being passed into InjectionContextValueProvider.GetValueFromInjectionContext<T>(...)
  2. IExtraDataContainer.GetExtraData(key); not returning object, but IExportLocatorScope.locate<T>(withKey: key); will. Looks like IExtraDataContainer is getting cast incorrectly from IExportLocatorScope.

XanNava avatar Nov 06 '22 02:11 XanNava

It looks like there was an issue in the auto configuration code that wasn't checking attributes on the method parameters.

I've released an updated version 8.0.0-RC824.

Note you need to specify the import on the parameter as well as the method

  class ServiceMain
  {
      public IService Service { get; set; }
      
      [Import]
      public void Recieve([Import(Key = "ServiceA")]IService service)
      {
          Console.WriteLine("Import through method");
          Service = service;
      }
  }

ipjohnson avatar Nov 06 '22 12:11 ipjohnson