I am doing dependency injection with Autofac. Everything goes great until I am trying to instantiate a dialog in another one using a delegate factory method (in order to call context.Forward on it), injected by Autofac.
private readonly Func<MyDialog> _myDialogFactory;
public RootDialog(Func<MyDialog> myDialogFactory)
{
SetField.NotNull(out _myDialogFactory, nameof(_myDialogFactory), myDialogFactory);
}
private async Task MessageReceivedAsync(IDialogContext context, IAwaitable<object> result)
{
...
var myDialog = _myDialogFactory();
await context.Forward(myDialog, ... );
...
}
Since RootDialog is marked as [Serializable] I obviously get the following exception:
Cannot serialize delegates over unmanaged function pointers, dynamic methods or methods outside the delegate creator鈥檚 assembly.
I know that a possible workaround would be to simply use the service locator pattern and do something like this. But I consider service locator an anti-pattern, so I am strictly against this solution.
How can I make it work using only dependency injection, like I am trying to do in the above example?
Two ideas
Thanks to Will's great advice, I was able to come up with the following solution:
builder.Register(context => new Func<MyDialog>(() => new MyDialog())).Keyed<Func<MyDialog>>(FiberModule.Key_DoNotSerialize).As<Func<MyDialog>>().SingleInstance();
The idea here is that in the Module where I am registering RootDialog and MyDialog with Autofac, I don't let Autofac to automatically generate the factory delegates for me, because those will end up in Autofac's assembly itself, hence the exception message in my previous comment. This way, I am registering my own factory delegate, overriding the automatically generated one, marking mine as a non-serializable singleton and now it works like a charm! :)
I'm struggling to solve similar situation like this for hours and using FiberModule.Key_DoNotSerialize works perfectly. Thank you @willportnoy and @peterbozso
Most helpful comment
Thanks to Will's great advice, I was able to come up with the following solution:
builder.Register(context => new Func<MyDialog>(() => new MyDialog())).Keyed<Func<MyDialog>>(FiberModule.Key_DoNotSerialize).As<Func<MyDialog>>().SingleInstance();The idea here is that in the Module where I am registering RootDialog and MyDialog with Autofac, I don't let Autofac to automatically generate the factory delegates for me, because those will end up in Autofac's assembly itself, hence the exception message in my previous comment. This way, I am registering my own factory delegate, overriding the automatically generated one, marking mine as a non-serializable singleton and now it works like a charm! :)