Autofac: Is there a hidden debug feature? - autofac

I remember I have read somewhere here in SO (maybe I was dreaming) that I can enable a "hidden" debug feature of Autofac, so that it can give me more information on what Autofac is doing in the background.
I asked because I just encountered a bug in my project. After I have added the following code into my AutofacModule:
builder.RegisterAssemblyTypes(typeof(MainWindowViewModel).Assembly)
.AssignableTo(typeof(ViewModelBase))
.EnableClassInterceptors()
.InterceptedBy(typeof(NotifyPropertyChangedInterceptor));
when compile, at:
using (var container = builder.Build())
{
...
}
Autofac throws:
System.NotSupportedException was unhandled. Parent does not have a default constructor. The default constructor must be explicitly defined.
But it didn't tell me which class does not have a default constructor (maybe I have missed something in the output window?). I ended up opened all my ViewModel classes one by one... to check if they have a default constructor.
So it would be wonderful for me if Autofac has a hidden debug feature. If not, is there an automatic way to find all classes which don't have a default constructor?
Thanks
(sorry for my English)

this isn't an Autofac exception - it looks like it might be a WPF one? If you can get the call stack from the debugger when the exception is thrown it should offer a clue.
Cheers!

Related

Autofac RegisterAssemblyTypes tries to resolve all public types

Quick question: I've been using autofac with asp.net core in a project and I've noticed that it tries to resolve all types during configuration after updating it to the latest nuget package (going from Autofac.Extensions.DependencyInjection 5.0.1 to 7.0.2). Btw, here's the code that was being used to register the types:
builder.RegisterAssemblyTypes(typeof(Utilizador).Assembly)
.AsImplementedInterfaces()
.AsSelf();
Until now, I wasn't seeing this behavior. The problem with this new approach is that it will try to resolve types that will never be injected through DI. For instance, it complains about public classes that don't have public constructors event though those classes will never be created through DI.
Can someone point me to when this change happened?
Does this mean that now I must filter the types I need explicitly?
Thanks.
This is nothing new.
You can filter those out with something like below:
builder.RegisterAssemblyTypes(ThisAssembly)
.Where(type => type.GetConstructors(BindingFlags.Public).Any())
.AsImplementedInterfaces();

Sharprepository Autofac InstancePerApiRequest in Webapi environment not working

Does anyone have a working example of sharprepository intergration with autofac using InstancePerApiRequest for DbContext?
I am registering my dbcontext thusly:
builder.RegisterType<AuditTestEntities>().As<DbContext>().InstancePerApiRequest();
If I remove the InstancePerApiRequest, sharprepository is able to get a dbcontext. But with the InstancePerApiRequest, I get the error message pasted below. Basically the crux of the error is, I suspect, the way sharprepository makes the call:
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
The full error stack:
iisexpress.exe Error: 0 : Operation=DefaultHttpControllerActivator.Create, Exception=System.InvalidOperationException: An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor. ---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor()' on type 'AccountRepository'. ---> Could not resolve type 'System.Data.Entity.DbContext' using the 'AutofacDependencyResolver'. Make sure you have configured your Ioc container for this type. View the InnerException for more details. (See inner exception for details.) ---> SharpRepository.Repository.Ioc.RepositoryDependencyResolverException: Could not resolve type 'System.Data.Entity.DbContext' using the 'AutofacDependencyResolver'. Make sure you have configured your Ioc container for this type. View the InnerException for more details. ---> Autofac.Core.DependencyResolutionException: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
Okay found the issue. There is a problem with using the SharpRepository AutofacDependencyResolver when using the MVC or Web API integration and trying to use the scope InstancePerApiRequest or InstancePerHttpRequest. Autofac expects those items to be resolved from the System.Web.DependencyResolver.Current instead of from the Autofac IContainer directly as the AutofacDependencyResolver is currently doing.
Here is how you can fix the issue right now until we make an overload for AutofacDependencyResolver that fixes the issue.
You will need to create your own dependency resolver within your project like this one:
public class CustomAutofacDependencyResolver : BaseRepositoryDependencyResolver
{
private readonly IDependencyResolver _resolver;
public CustomAutofacDependencyResolver(IDependencyResolver resolver)
{
_resolver = resolver;
}
protected override T ResolveInstance<T>()
{
return _resolver.GetService<T>();
}
protected override object ResolveInstance(Type type)
{
return _resolver.GetService(type);
}
}
And then register it with SharpRepository so it will use it to resolve the DbContext and then it will work as expected.
RepositoryDependencyResolver.SetDependencyResolver(new CustomAutofacDependencyResolver(DependencyResolver.Current));
** Update**
I was testing with MVC and able to replicate the error and fix it but that doesn't work with Web API. I am used to using StructureMap where it works fine using the GlobalConfiguration.Configuration.DependencyResolver.
It seems the issue is that Autofac needs a IDependencyScope that you can access from the HttpRequestMessage but I'm not seeing a way to get to that outside of the ApiController. This describes the issue and the reason: https://groups.google.com/forum/#!msg/autofac/b3HCmNE_S2M/oMmwFE5uD80J
Unfortunately right now I'm at a bit of a loss on the best way to handle this. But I'll keep thinking about it.
So, I was able to get mine working by changing the lifetime scope to InstancePerLifetimeScope. I don't know whether this has any unforeseen consequences or not. Everything appears to be working fine for me so far.

GWT Deferred binding failed for custom class: No class matching "..." in urn:import:

I am developing a couple of custom widgets that I would like to be able to use with UiBinder. Unfortunately I keep wasting my life away with chasing down the following error:
No class matching "..." in urn:import:...
This seems to be the catch-all exception that is thrown any time there is any error in the class that prevents the GWT compiler from processing it. This includes anything in the class's entire dependency tree.
To save myself and anyone of you who is running into the same issue some time and pain, let's compile a list here of the most unexpected and hard to find causes for this. I'll start with my latest one, which has made me decide to post this here.
I was using a CellList thusly:
private static RelationshipViewerUiBinder uiBinder = GWT.create(RelationshipViewerUiBinder.class);
#UiField(provided=true)
CellList<String> prioritisedDisplay;
public RelationshipViewer() {
prioritisedDisplay = new CellList<>(new TextCell());
initWidget(uiBinder.createAndBindUi(this));
}
note the Java 7 style <> on the CellList. Despite my IDE's protestations to the contrary, it turns out you DO need to explicitly say CellList< String> in that new call, or it wont compile and all you get is the above mentioned error. Thanks by the way, the existance of this question prompted me to scrutinise my code and probably saved me a couple of hours! This fixed it:
private static RelationshipViewerUiBinder uiBinder = GWT.create(RelationshipViewerUiBinder.class);
#UiField(provided=true)
CellList<String> prioritisedDisplay;
public RelationshipViewer() {
prioritisedDisplay = new CellList<String>(new TextCell());
initWidget(uiBinder.createAndBindUi(this));
}
I had written a component that used the GWT JSON functionality, but hadn't imported com.google.gwt.json.JSON into the module.
Thanks to your message here, this was only 2 hours down the drain...
I wrote a helper-class that this widget uses somewhere deep inside its dependency tree.
For this helper-class, I told Eclipse to auto-generate the hashCode() and equals(...) functions. The class contained a field of type double, for which Eclipse generates code that uses Double.doubleToLongBits().
Turns out GWT does not implement this method on its version of Double. But of course, neither does Eclipse detect this as a possible compile-error, nor does it cause any issues in Dev Mode if I use the widget inside the GWT-App's Java code rather than inside UiBinder.
3 hours down the drain... Great... Yay for helpful error messages.
UPDATE:
As of GWT 2.5.0 (RC1) GWT now supports Double.doubleToLongBits() rendering this particular error obsolete, but the general error mechanism of a missing JRE emulation remains and will probably manifest itself in a similarly unhelpful way.
I was trying to use a GwtQuery DragAndDropCellTree in a UiBinder .ui.xml, which was impossible as DragAndDropCellTree has no zero-arg constructor.
See more details

Prism 4.0 : Overriding InitializeShell() Method

I've been going through the documentation for creating Prism applications and setting up the Shell seems to be split into 2 methods, CreateShell() and InitializeShell()
For CreateShell I simply have:
protected override DependencyObject CreateShell()
{
return ServiceLocator.Current.GetInstance<Shell>();
}
The documentation says that code is needed in the IntializeShell() method to ensure it is ready to be displayed. The following is given as an example:
protected override void InitializeShell()
{
Application.Current.MainWindow = (Window)this.Shell;
Application.Current.MainWindow.Show();
}
I have noticed however that if I omit the first line and just call the Show() method it seems to work (MainWindow already appears to have Shell assigned to it). Can you tell me why this is the case, and why we still need to explicity set the MainWindow property here?
Also as I did not specifically register Shell to an interface within the container, how is it able to resolve Shell in CreateShell()?
Question 1: Why does just calling Show() seem to work and why is Application.Current.MainWindow seem to be populated?
There are a few things you should check here. In a typical WPF application, the type for the main window can be specified in the App.xaml. If it is specified, WPF will instantiate one of those for you. This is not desirable because WPF won't use your container to instantiate your shell and any dependencies won't be resolved.
When you run that first line of code in InitializeShell, you'd be replacing the WPF-instantiated Shell object with the one you manually instantiated.
I looked at the code for the MEF and Unity bootstrappers and I don't see anywhere that MainWindow is being set, but I don't know if you might have customized the base bootstrappers, so that's something else to look for.
Show() works because you are simply showing the window you instantiated and the WPF-instantiated one isn't shown. This is my theory, but without seeing your code, it'd be tough to say for sure.
Question 2: How can Unity resolve something that hasn't been registered?
Unity can always resolve a concrete type, regardless of registration. It cannot resolve non-concrete classes that haven't been mapped to a concrete type. This is why Resolve<Shell> works, but Resolve<IMyInterface> doesn't unless you register a type.

Programatic property injection with Microsoft Unity

I use contructor injection in my solution, but this one class has a property that i do not want to pass in the constructor where i have the invariant dependencies.
Let's say i got an ILogger and it has a FileName property i want to set, while still having it set the dependancies in the contructor.
How do i go about registering the type, and at the same time pass the defaunt connection string.
I hope there is an easy way to do it - preferably without decorating the property with an attribute, but if the setup is easier with the attribute i guess that's cool :)
So the question is, how do i inject a property value on an object that also uses contructor injection - with Unity.
UPDATE: I mentioned it in the title, but i forgot to elaborate in the body of the text - i want to set these dependencies up manually (in code) as opposed to in a config file.
Ok i guess it helped to ask the question, i found out - here it is.
container.Configure<InjectedMembers>().ConfigureInjectionFor<BasicLogger>(
new InjectionProperty("FileName", #"C:\test.log")
);
If you are injecting properties you have to use [Dependency] or else manually inject that dependency.
You usually want an IConfiguration interface to be injected. This would probably have a LogFile property that you can read.
The Configuration implimentation is usually just a simple wrapper to read items from the config file.