Hiro icon indicating copy to clipboard operation
Hiro copied to clipboard

when publishing a delegate or class with missing dependencies, hiro will throw a ConstructorNotFound exception

Open juancastrodlc opened this issue 13 years ago • 3 comments

in the sample assembly add a simple delegate

public delegate void Procedure();

Hiro attempts to find a constructor and will fail

also when adding a class to the sample assembly

public interface ISomeInterface{}

public SomeClass:ISomeInterface { public SomeClass(Type missingDependency){} }

will throw the same error.

Is this by design or is it a Bug?

If it is I'm working on the patch.

Greetings.

juancastrodlc avatar May 24 '11 22:05 juancastrodlc

Hiro throws a ConstructorNotFoundException whenever a dependency is not found and this behavior is done by design. The reason why Hiro can't find a constructor on your sample Procedure delegate is that the constructor signature looks like this in IL:

.method public hidebysig specialname rtspecialname 
    instance void .ctor (
        object object,
        valuetype [mscorlib]System.IntPtr method
    ) runtime managed 

The first parameter required by the delegate has to be the target object instance, and the second parameter is the System.IntPtr pointer that points to the method that you want to execute. In this case, Hiro will automatically throw the ConstructorNotFoundException because it doesn't know how to pass in an object instance and the given method pointer. The only workaround for this issue is to tell Hiro that you want to resolve the delegate at runtime, and you can do that by using the DependencyMap.AddDeferredService<T>() method:

var map = new DependencyMap(); yourMap.AddDeferredService<Procedure>();

Once you have the deferred service in place, you'll have to implement a custom IMicroContainer instance and chain it to the compiled container's NextContainer property so that Hiro will forward its request for a Procedure delegate to the next container:

var yourContainer = yourMap.CreateContainer(); yourContainer.NextContainer = new SomethingThatCanCreateProcedureDelegates();

// Use the container just like you normally would use it var someProcedure = yourContainer.GetInstance<Procedure>();

philiplaureano avatar May 24 '11 23:05 philiplaureano

Reposting from the comment on the closed pull request: (let's see) if I can convey how I plan to use Hiro and you can give me pointers to create some extension points:

  1. delegate declarations which will be used externally (i.e. by final user) should not be considered services, I found this problem using the source for LinqBridge and conditional compilation. When i use the bridge, Hiro tells me it has dependencies missing in the first Func and or Proc delegate declaration it finds. update: automatically registered as deffered services
  2. properties wich are primitive types, value types and strings should not be considered as dependencies (i.e. for constructor injection) or services (i.e. as injectable properties) update: I think hiro does filter valuetypes but does not filter strings
  3. if there is an actual dependency missing in some service implementations it should ignore this service as part of the compiled container do not throw exceptions, defer it to the unit test to ensure instantiation. update: register as deffered service
  4. when another map is instantiated which contains the missing dependencies, chain a new container with those dependencies. update: chain it to container.NextContainer In my fork Hiro/master branch i actually made all the unit tests pass and added these files to the SampleAssembly: Delegates.cs which contains one delegate declaration IMising.cs which contains an interface which will be implemented by an 'incomplete' service class SampleMissingDependency.cs which contains the implementation of the incomplete service IMissing and in the UnitTests project: BugFixes.cs added test ShouldReturnNullWhenTryingToInstantiateAnIncompleteDependency

If you add these classes without using my modifications to ConstructorResolver.cs the Delegate.cs declaration produces several errors through your unit tests including my own. (this in my opinion is an actual bug, a delegate declaration is always complete, the compiler takes care of its dependencies) Update: on thinking a bit harder a delegate is a way to have a short service (i.e. a single method interface), however could they register themselves as defferred by default? Otherwise we have to configure potentially many services by hand on each map loader, in other words conventions stops working.

I can't find how to filter missing constructor parameters without messing with the source.

juancastrodlc avatar May 26 '11 20:05 juancastrodlc

  1. You can add support for delegates by adding an IImplementation implementation that specifically resolves a delegate using the the NextContainer property. The TransientType class was built to resolve non-delegate types, and the reason why you're getting errors is that it assumes that you're using the delegate type as a regular service with dependencies that are available in the map, which would be incorrect in this case.
  2. You can solve this issue by overriding and filtering the GetMissingDependencies and GetRequiredDependencies methods (presumably using a decorator) so that they only return dependencies that are reference types.
  3. If you'll be providing the actual service implementation at runtime, then you can just use DependencyMap.AddDeferredService() to explicitly list the services that you need and then use the NextContainer property to supply the service instances. If you need to explicitly ignore missing dependencies and need to have more control over the services that need to be in the map, you can decorate and override the GetImplementations() method so that it returns the dependencies you need (including the missing dependencies).
  4. Hiro already supports DependencyMap chaining by default. For example:

var map1 = new DependencyMap(); var map2 = new DependencyMap();

var combinedMap = map1 + map2;

var combinedContainer = combinedMap.CreateContainer();

Try that out and let me know if that helps.

On Fri, May 27, 2011 at 4:54 AM, juancastrodlc < [email protected]>wrote:

Reposting from the comment on the closed pull request: (let's see) if I can convey how I plan to use Hiro and you can give me pointers to create some extension points:

  1. delegate declarations which will be used externally (i.e. by final user) should not be considered services, I found this problem using the source for LinqBridge and conditional compilation. When i use the bridge, Hiro tells me it has dependencies missing in the first Func and or Proc delegate declaration it finds.
  2. properties wich are primitive types, value types and strings should not be considered as dependencies (i.e. for constructor injection) or services (i.e. as injectable properties)
  3. if there is an actual dependency missing in some service implementations it should ignore this service as part of the compiled container do not throw exceptions, defer it to the unit test to ensure instantiation.
  4. when another map is instantiated which contains the missing dependencies, chain a new container with those dependencies.

In my fork Hiro/master branch i actually made all the unit tests pass and added these files to the SampleAssembly: Delegates.cs which contains one delegate declaration IMising.cs which contains an interface which will be implemented by an 'incomplete' service class SampleMissingDependency.cs which contains the implementation of the incomplete service IMissing and in the UnitTests project: BugFixes.cs added test ShouldReturnNullWhenTryingToInstantiateAnIncompleteDependency

If you add these classes without using my modifications to ConstructorResolver.cs the Delegate.cs declaration produces several errors through your unit tests including my own. (this in my opinion is an actual bug, a delegate declaration is always complete, the compiler takes care of its dependencies)

I can't find how to filter missing constructor parameters without messing with the source.

Reply to this email directly or view it on GitHub: https://github.com/philiplaureano/Hiro/issues/2#comment_1245347

philiplaureano avatar May 26 '11 23:05 philiplaureano