I want to wrap a library using a Func < T , ISomething > as a method parameter, with ISomething being part of the library. My wrapper should have all the references to the library and somebody who uses the wrapper should not need to reference the library.
I want to wrap the Autofac Register method (with lambda expressions), like here https://autofaccn.readthedocs.io/en/latest/register/registration.html#lambda-expression-components
I somehow need to convert the
Func<IDependencyContainer, T> delegate1
to a
Func<IComponentContext, T> delegate1
This is what my current try looks like:
public IDependencyContainerToAddOptions<T> WrapperRegister<T>
(
Func<IDependencyContainer, T> delegate1
)
{
return new DependencyContainerToAddOptions<T>(_containerBuilder.Register(delegate1));
}
TLDR:
How to wrap the Register method of Autofac, which can be called like this:
_builder.Register(ctx =>
{ var profileService = ctx.Resolve<IUserProfileService>();
and which is defined like that:
/// <summary>
/// Register a delegate as a component.
/// </summary>
/// <typeparam name="T">The type of the instance.</typeparam>
/// <param name="builder">Container builder.</param>
/// <param name="delegate">The delegate to register.</param>
/// <returns>Registration builder allowing the registration to be configured.</returns>
public static IRegistrationBuilder<T, SimpleActivatorData, SingleRegistrationStyle>
Register<T>(
this ContainerBuilder builder,
Func<IComponentContext, T> delegate1)
{
if (delegate1 == null) throw new ArgumentNullException(nameof(delegate1));
return builder.Register((c, p) => delegate1(c));
}
The user of the wrapper must not have to add dependencies to Autofac.
It looks like what you're trying to do overlaps a lot with this FAQ in the Autofac docs asking how to keep Autofac references out of your app. In particular, you're asking how to effectively replicate Autofac some registration syntax, I'm guessing so your apps can register things without referencing Autofac.
There are some good reasons to do that, but I might try to convince you not to. As noted in that FAQ:
You will potentially sink a lot of time into writing abstractions and wrappers around things only to replicate a lot of Autofac-specific syntax and capabilities.
This same sort of "isolate oneself from references" also happens a lot with logging, and there aren't a lot of super great solutions for that, either.
With the emergence of .NET Core one way to go would be to use the Microsoft.Extensions.DependencyInjection abstractions. Register things with the IServiceCollection
there and then you can use the Autofac.Extensions.DependencyInjection package to push those registrations into an Autofac container. This limits you to what the abstractions support, but it gives you abstractions you don't have to maintain.
But, again, let's say you really want to maintain your own. If you want people to register Func<IComponentContext, T>
then you should realize that IComponentContext
is an Autofac thing and that breaks your isolation. You mentioned that in the update at the bottom, that you want your users to not have references to Autofac... but consider, again, that you'll need to mirror all the Autofac behavior and syntax.
So if you're going to do that, you'll need to do create wrappers and abstractions. A LOT of wrappers and abstractions. More than will be worth maintaining. The pattern will be:
Something like:
public interface IMyComponentContext
{
T Resolve<T>();
}
public class ComponentContextWrapper : IMyComponentContext
{
private readonly IComponentContext _autofacContext;
public ComponentContextWrapper(IComponentContext autofacContext)
{
_autofacContext = autofacContext;
}
public T Resolve<T>()
{
return this._autofacContext.Resolve<T>();
}
}
It's going to be a lot. Then...
IComponentContext
.// In the place where you actually register your delegates, you'll have
// to provide wrappers for your clients:
builder.Register((c, p) => delegate1(new ComponentContextWrapper(c)));
If I haven't already made it clear, I have a pretty strong opinion that this is a Bad Idea. It's a lot of work and unless there's really some potential need to move away from Autofac, there's no real payoff for maintaining the abstractions, testing them, etc. However, that's what you'll need to do if you want to keep that separation. Good luck!