zcz527 / autofac

Automatically exported from code.google.com/p/autofac
Other
0 stars 0 forks source link

Calling Resolve<IEnumerable<TypeName>>() on empty container returns object #369

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1.Create container using ContainerBuilder (no need to Register any items)
2.Resolve an IEnumerable of any type

What is the expected output? What do you see instead?

Resolve call should return null, but instead returns empty array.

What version of Autofac are you using? On what version of .NET/Silverlight?

Autofac 2.6.1.841 (also confirmed in 2.5 and 2.4), .Net 4.0

Please provide any additional information below.

I have attached a sample VS 2010 project

Original issue reported on code.google.com by biscuita...@gmail.com on 22 May 2012 at 9:36

Attachments:

GoogleCodeExporter commented 8 years ago
I discovered this issue while using the 
Autofac.Integration.Web.Forms.InjectProperties attribute, but it seems to 
affect only the Core library.

Original comment by biscuita...@gmail.com on 22 May 2012 at 9:41

GoogleCodeExporter commented 8 years ago
After searching through the source code, and wiki, I discovered this is correct 
behavior based on this page:
http://code.google.com/p/autofac/wiki/RelationshipTypes

I disabled the default behaviors (using a flag that doesn't seem to be 
documented anywhere):
var builder = new ContainerBuilder();
var container = builder.Build(ContainerBuildOptions.ExcludeDefaultModules);

But this caused MVC integration to fail because it relies heavily on 
IEnumerable/Meta/Lazy behavior in the default modules.

It seems the creation of the IEnumerable<TypeName> happens on 
context.IsRegistered(IEnumerable<TypeName>).  Is it possible for this to return 
false instead of creating an empty TypeName[] if there are no TypeName objects 
in the container? 

With the current behaviour, my public IEnumerable<TypeName> {get;set;} that I 
have defined lots of places in my ASP.NET pages and also MVC Controllers are 
getting set with empty arrays and then overwritten.  It seems like they should 
not be set in the first place if there are no TypeName objects in the container.

Original comment by biscuita...@gmail.com on 23 May 2012 at 6:56

GoogleCodeExporter commented 8 years ago
Hi there - glad you were able to get to the bottom of this. If you use 
ExcludeDefaultModules, you can re-add the ones you need using code like:

builder.RegisterSource(new LazyRegistrationSource())

etc... You could then register a modified version of the default 
CollectionRegistrationSource (responsible for IEnumerable etc) that does not 
return results when the element type is not registered.

Not a lot of other simple options that I can think of, hope you have some 
success working through this.

Regarding MVC controllers, you may be able to turn off (not turn on) property 
injection, and instead use an OnActivated() handler to perform property 
injection selectively (e.g. ignoring properties on base types).

Nick

Original comment by nicholas...@gmail.com on 24 May 2012 at 5:00

GoogleCodeExporter commented 8 years ago
Thanks for the response.  LazyRegsitrationSource is not a public class (nor are 
any of the IRegistrationSource implementations).  I tried to use 
ExcludeDefaultModules and re-register everything but 
CollectionRegistrationSource, and it didn't work.

It seems to me that the container should return something when you call 
c.Resolve<IEnumerable<TypeName>> *only* if there has been one or more TypeName 
objects registered in the container.  Otherwise Resolve should throw and 
IsRegistered should return false.  I don't see the usefulness of returning an 
empty array.

It only affected one control in my code: IEnumerable<string> PropertyName had a 
set method that was accessing an injected property that had not yet been 
injected.  I was able to work around it in this case.

Original comment by biscuita...@gmail.com on 24 May 2012 at 3:28

GoogleCodeExporter commented 8 years ago
Thanks for following up. There are pros and cons to each approach, we don't 
plan to change this but want to make sure that the right workarounds are in 
place in situations like the one you've identified. Thanks again for the report!

Original comment by nicholas...@gmail.com on 16 Jun 2012 at 3:13

GoogleCodeExporter commented 8 years ago
I just added Autofac to a webforms project ran into this trap. I am wondering 
if you could describe what the pros of the current implementation are. Seems 
like a pretty nasty surprise.

Original comment by mte...@gmail.com on 15 Apr 2013 at 7:03

GoogleCodeExporter commented 8 years ago
The issue is no longer about which approach is better, it is the fact that 
there is now a great deal of code that will be relying on this behaviour, and 
changing it will break that code.

Original comment by alex.meyergleaves on 16 Apr 2013 at 1:39