Skip to content

Instantly share code, notes, and snippets.

@pizycki
Created March 13, 2019 21:31
Show Gist options
  • Select an option

  • Save pizycki/f2768236c450d12a405896112e170eed to your computer and use it in GitHub Desktop.

Select an option

Save pizycki/f2768236c450d12a405896112e170eed to your computer and use it in GitHub Desktop.
MSDI alternative for Autofac service resolving with parameter
using System;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace InjectDependencyWithProperty.src
{
public class UsersStorage
{
public void Create(object user)
{
// do nothing
}
}
public class ServiceContext // Service Fabric
{
public T GetRemotingService<T>() => Activator.CreateInstance<T>();
}
// Can turn into delegate
public interface ICreateUserServiceFactory
{
ICreateUserService Create(ServiceContext serviceContext);
}
//public class CreateUserServiceFactory : ICreateUserServiceFactory
//{
// private readonly IServiceProvider _serviceProvider;
// public CreateUserServiceFactory(IServiceProvider serviceProvider)
// {
// _serviceProvider = serviceProvider;
// }
// public ICreateUserService Create(ServiceContext dependency)
// {
// var createUserService = _serviceProvider.GetService<CreateUserService>();
// var contextInjectable = (IDependencyViaProperty<ServiceContext>)createUserService;
// contextInjectable.Dependency = dependency;
// return createUserService;
// }
//}
public class CreateUserServiceFactory : ICreateUserServiceFactory
{
private readonly GenericPropertyInjectionFactory<ICreateUserService, CreateUserService, ServiceContext> _factory;
public CreateUserServiceFactory(GenericPropertyInjectionFactory<ICreateUserService, CreateUserService, ServiceContext> factory)
{
_factory = factory;
}
public ICreateUserService Create(ServiceContext serviceContext) => _factory.Create(serviceContext);
}
public class GenericPropertyInjectionFactory<TContract, TImplementation, TDependency>
where TImplementation : TContract, IDependencyViaProperty<TDependency>
{
private readonly IServiceProvider _serviceProvider;
public GenericPropertyInjectionFactory(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public TContract Create(TDependency dependency)
{
if (dependency == null) throw new ArgumentNullException(nameof(dependency));
var serviceInstance = _serviceProvider.GetService<TImplementation>();
var dependencyInjectable = (IDependencyViaProperty<TDependency>)serviceInstance;
dependencyInjectable.Dependency = dependency;
return serviceInstance;
}
}
public interface ICreateUserService
{
// Contract remains clear
void CreateUser(string userName);
}
public interface IDependencyViaProperty<in T>
{
/// <summary>
/// Dependency injection point. Use instead of injecting via constructor.
/// </summary>
/// <exception cref="InvalidOperationException">Thrown when instance of Service Context has been already assigned in the instance.</exception>
T Dependency { set; }
}
public class CreateUserService : ICreateUserService, IDependencyViaProperty<ServiceContext>
{
private ServiceContext _serviceContext;
ServiceContext IDependencyViaProperty<ServiceContext>.Dependency
{
set
{
_serviceContext = _serviceContext == null
? value
: throw new InvalidOperationException("Service Context already injected!");
}
}
public void CreateUser(string userName)
{
var storage = _serviceContext.GetRemotingService<UsersStorage>();
storage.Create(new
{
Name = userName
});
}
}
public class Runner
{
[Fact]
public void Main()
{
var services = new ServiceCollection();
services.AddTransient<CreateUserService>();
services.AddTransient(typeof(GenericPropertyInjectionFactory<,,>));
services.AddTransient<ICreateUserServiceFactory, CreateUserServiceFactory>();
var provider = services.BuildServiceProvider();
var createUserServiceFactory = provider.GetService<ICreateUserServiceFactory>();
var serviceFabricContext = new ServiceContext();
var createUserService = createUserServiceFactory.Create(serviceFabricContext);
createUserService.CreateUser("Paweł Iżycki");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment