How would one provide an IComponentContext func to a type Registration where the parameters could be either types (to be resolved) or parameters passed in?
So if I have a func I'd like to use for registration such as this:
public static ClassTarget Resolver(ClassArg1 arg1, ClassArg2 arg2)
{
// Do something fancier than this...
return new ClassTarget(arg1, arg2);
}
How would I register that for ClassTarget
?
A full example, with the hack I'm currently using and alternate registration that work (as one would expect):
public class ClassArg1 { }
public class ClassArg2 { }
public class ClassTarget
{
public ClassTarget(ClassArg1 arg1, ClassArg2 arg2) { }
}
public static class ResolveFuncTest
{
public static ClassTarget Resolver(ClassArg1 arg1, ClassArg2 arg2)
{
// Do something fancier than this...
return new ClassTarget(arg1, arg2);
}
private static T GetArgValue<T>(IComponentContext componentContext, IEnumerable<Parameter> parameters)
{
if (parameters != null)
{
var param = parameters.OfType<TypedParameter>().FirstOrDefault(p => p.Type == typeof(T));
if (param != null)
{
return (T)param.Value;
}
}
return componentContext.Resolve<T>();
}
public static void Test()
{
var builder = new ContainerBuilder();
// The first argument will be resolved as normal
builder.RegisterType<ClassArg1>().AsSelf().SingleInstance();
// Works - just a typical type registration without the Func used
//builder.RegisterType<ClassTarget>().AsSelf().SingleInstance();
// Works - but only if we know how to resolve the arguments as types or parameters
//builder.Register((c, p) => Resolver(c.Resolve<ClassArg1>(), p.TypedAs<ClassArg2>())).AsSelf().SingleInstance();
// Works - smells though!
builder.Register((c, p) => Resolver(GetArgValue<ClassArg1>(c,p), GetArgValue<ClassArg2>(c, p))).AsSelf().SingleInstance();
// Build/scope
var context = builder.Build();
var scope = context.BeginLifetimeScope();
// The second argument is passed as an instance/parameter at resolve time
scope.Resolve<ClassTarget>(new TypedParameter(typeof(ClassArg2), new ClassArg2()));
}
}
Clearly I misunderstand something core here, since I'm stumbling over myself to do the parameter resolution that Autofac normally does so seamlessly! Is there just another overload to Resolve
I'm missing in the documentation?
If you have to do your initialization entirely inside that
Resolver
function, you are probably stuck using the mechanism you have now. That is, if you have a specific function and, for whatever reason, you have to both instantiate theClassTarget
object and you have to initialize it there, you're stuck.If you can refactor a bit, you can use the delegate factories feature of Autofac to your advantage.
Here's an example of what the code could look like if you refactored a bit and used the delegate factory feature:
I'm guessing this is a little closer to what you were hoping to achieve.