New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assembly scanning registers private classes by default #897
Comments
Interesting find. We have some tests around assembly scanning. I should add some internal/private items and see about reproducing this. |
Looks like we had just never tested this. I've updated things so it only locates public/nested public classes. Fix will be out in 4.7.1. |
Hi @tillig , the change in registering internal classes is a breaking change IMO, and it took me a while to figure out why the product started to fail in some weird places. :( I'd be in favour to revert to the previous behaviour as @reservedwords suggested ("The behaviour with internal classes seems sensible, and I'm happy to update the docs to reflect this"). If you think that's not a good idea for any reason, I think that this change deserves a minor version bump, and not only a patch one, to follow the semver specification. Also, I find registering the To let you understand my scenario, I have a bunch of classes that implement an interface, and are registered as:
These classes have a lot of dependencies:
In a scenario that all these Do you see any workaround for this, other than resigning from using |
The behavior was really only intended to support public types and we only had tests actually validating the public type scanning so it's sort of hard to say from a long-term standpoint (e.g., before I was on the project) what the original intent was. However, I'm pretty confident internal and private wasn't the intent, because consider a different scenario: cb.RegisterAssemblyTypes(NotThisAssembly)
.Where(t => typeof(IInternal).IsAssignableFrom(t))
.InstancePerDependency()
.As<IInternal>(); The only time internal types make sense is when scanning the current assembly, but really no other assembly... unless there's also Further, there are a lot of other Autofac behaviors that only work with public types, like type and interface interceptors. Working with your exposed/public API by default makes sense. Whether or not this is fixing a bug in behavior or breaking is debatable since the intended behavior only ever was to use the public API, so if folks were taking advantage of the incorrect behavior... it breaks that, sure, but it wasn't behavior that was intentional anyway. But it's out there now, so it's a little moot. Folks have taken it and unlisting it really isn't going to happen at this point. However, I do understand the desire to enable scanning of internal types so I'd like to offer a compromise: What if we added an assembly scanning override that allows you to specify a flag/parameter that would enable scanning for non-public types? Something like: cb.RegisterAssemblyTypes(ThisAssembly, includeNonPublic: true)
.Where(t => typeof(IInternal).IsAssignableFrom(t))
.InstancePerDependency()
.As<IInternal>(); Would that get you what you need? |
I suppose from a back-compat standpoint, I'd also be willing to invert that: cb.RegisterAssemblyTypes(ThisAssembly, publicOnly: true)
.Where(t => typeof(IInternal).IsAssignableFrom(t))
.InstancePerDependency()
.As<IInternal>(); |
@alexmg Before I make a change here, do you have any insight as to the original intent of the feature and a preference on how you think we should go? |
@tillig, thanks for answering so promptly. A few random thoughts from my side:
|
@Greg-Smulko It is possible to proxy internal interfaces, but note the docs also say:
That's why I mentioned earlier
But, I thought of a better compromise to this that will help:
Does that sound reasonable? I hope that will work for folks. I'd still be interested in what @alexmg has to say, but I'll get working on this. |
OK, folks, check this out and see what you think. I added the If that looks good, I'll cut a quick 4.8 to avoid too many people getting bitten with this. |
@tillig , it looks good to me. I'm happy that backwards compatibility is not broken anymore. :) |
Hello guys, I've updated nuget of Autofac from 4.6.2 to 4.7.1 and now assemblyscanner ignores internal classes what is not good because I don't want to make them public, the implementation of public interfaces it should be hidden by internal modifier. How can I fix this?? I see the solution from @tillig how can I get it via nuget it is not available |
US west coast, so UTC-7 right now with daylight saving. Also, Autofac isn't my job, so sometimes it gets to wait a bit as I actually do things that pay the bills. ;) (We're looking for help if folks are interested...) I was hoping to hear from @alexmg before cutting the 4.8 but it seems like it'd be better to just roll forward and call it good. |
I just pushed 4.8.0 with the revert in behavior and a new |
According to the documentation, assembly scanning will by default register all public, concrete classes in an assembly. In fact, assembly scanning goes further than that and registers internal and nested private classes:
The behaviour with
internal
classes seems sensible, and I'm happy to update the docs to reflect this, but registering nested private classes seems to violate the principle of least surprise. Assuming that private classes wouldn't be registered led to unexpected registrations and bugs in an application I was working on.I think the default behaviour should exclude nested private classes. I'm happy to cook up a PR, but realise this is potentially a breaking change and wanted discussion before diving in.
I've observed this behaviour on Autofac 3.5.2 and 4.6.2, on full .NET Framework
The text was updated successfully, but these errors were encountered: