Just starting to to use Autofac & i'm not sure how to deal with a situation I hit correctly. I have a factory where the type I pass back has a dependency on an interface i'm injecting with autofac. Here is my autofac config for the specific component i'm having an issue with:
builder.RegisterType<EmployerFunctions>().As<IEmployerFunctions>();
Here is a factory where i'm having the issue:
public static IMetaDataSaver GetMetaDataFactory(HttpRequestMessage request)
{
if (request.IsReciprocal())
{
return new ReciprocalMetaDataSaver();
}
else
{
return new EmployerMetaDataSaver(); //<--error is here
}
}
The constructor of EmployerMetaDataSaver() has an IEmployerFunctions passed in. I could be lazy of course and new up a new EmployerFunctions but i don't want to do that.
You can create delegate factory for IMetaDataSaver objects:
builder.RegisterType<EmployerFunctions>().As<IEmployerFunctions>();
builder.Register<Func<HttpRequestMessage, IMetaDataSaver>>(delegate(IComponentContext context)
{
if (request.IsReciprocal())
{
return new ReciprocalMetaDataSaver();
}
else
{
IComponentContext cc = context.Resolve<IComponentContext>();
var functions = cc.Resolve<IEmployerFunctions>();
return new EmployerMetaDataSaver(functions); //<--error is here
}
});
If you need to create IMetaDataSaver for HttpRequestMessage you can resolve delegate factory and call it with concrete HttpRequestMessage object:
// example with the explicit use container. Use DI instead in real code
Func<HttpRequestMessage, IMetaDataSaver> factory = container.Resolve<Func<HttpRequestMessage, IMetaDataSaver>>();
var dataSaver = factory(requestMessage);
Also, you can use ordinary factory and DI for it:
builder.RegisterType<EmployerFunctions>().As<IEmployerFunctions>();
builder.RegisterType<MetaDataSaverFactory>().As<IMetaDataSaverFactory>();
Factory class will look something like next one:
public interface IMetaDataSaverFactory
{
IMetaDataSaver GetMetaDataFactory(HttpRequestMessage request);
}
public class MetaDataSaverFactory : IMetaDataSaverFactory
{
private IEmployerFunctions _functions;
public MetaDataSaverFactory(IEmployerFunctions functions)
{
_functions = functions;
}
public static IMetaDataSaver GetMetaDataFactory(HttpRequestMessage request)
{
if (request.IsReciprocal())
{
return new ReciprocalMetaDataSaver();
}
else
{
return new EmployerMetaDataSaver(_functions);
}
}
}
Related
I've a concrete Service and it's behaviour differs by it's parameters, I could not achieve to Register and Resolve it by Autofac. As you can see it is so easy to implement it by custom Container. How can I use Autofac for this requirement?
public class Container
{
Dictionary<string, MyService> _components = new Dictionary<string, MyService>();
void Register(string key,string param, string param2)
{
_components.Add(key, new MyService(param, param2, ResolveRepository()));
}
MyService ResolveMyService(string key)
{
return _components[key];
}
IRepository ResolveRepository()
{
throw new NotImplementedException();
}
}
public class MyService
{
public MyService(string param,string param2,IRepository rep ) { }
}
public interface IRepository { }
EDIT: I'm trying the solve registration in Autofac, but we have no Container during Registration process.
builder.RegisterType<MyService>()
.Named<MyService>("Service1")
.OnActivating(e =>
{
e.ReplaceInstance(new MyService("Service1", "param1-23", Container.Resolve<IRepository>()));
});
You can access the container during the Activating pseudo event by using e.Context
builder.RegisterType<MyService>()
.Named<MyService>("Service1")
.OnActivating(e =>
{
MyService s = new MyService("Service1",
"param1-23",
e.Context.Resolve<IRepository>())
e.ReplaceInstance();
});
but another option would be to use the WithParameter method.
builder.RegisterType<MyService>()
.Named<MyService>("Service1")
.WithParameter("param1", "Service1")
.WithParameter("param2", "param1-23");
I want to give a caller of my class ability to choose provider by name, instead of passing the provider concrete class as standard DI recommends. It will allow to hide actual implementation details from client, still giving control which provider to use. We've done it by implementing factory
public ICurrencyProvider GetCurrencyServiceProvider(string providerName)
{
switch (providerName)
{
case "CurrencyLayerAPI":
{ currencyService = new CurrencyLayerWrapper(); }
break;
case "XE":
{ currencyProvider = new XEWrapper(); }
break;
}
return _currencyProvider;
}
and constuctor expects providerName as a parameter.
However for unit tests I wish to use Substitute, not concrete class of provider.
I ended up with 2 parameters, responsible for the same choice- name for production code and interface for calls from tests.
public CurrencyProcessor(string providerName, ICurrencyProvider substituteCurrencyProvider =null)
{
if(!providerName .IsNullOrEmpty())
{
_currencyProvider = GetCurrencyServiceProvider(providerName);
}
else
{ _currencyProvider =substituteCurrencyProvider;
}
}
Slightly alternative implementation is to read providerName from configuration instead of passing it as a parameter.
public CurrencyProcessor(IConfigurationProvider configurationProvider, ICurrencyProvider substituteCurrencyProvider =null)
{
_providerName = _configurationProvider.GetAppSetting("CurrencyProviderToUse");
if(!providerName .IsNullOrEmpty())
{
_currencyProvider = GetCurrencyServiceProvider(providerName);
}
else
{ _currencyProvider =substituteCurrencyProvider;
}
}
I wander, is any better way exist to have single parameter to control creation of internal object, but avoiding giving responsibility to create object to a client.
Related discussions
How to use Dependency Injection without breaking encapsulation?
Preferable way of making code testable: Dependency injection vs encapsulation
https://softwareengineering.stackexchange.com/questions/344442/dependency-injection-with-default-construction
since in your constructor your are statically creating your provider, just inject the provider.
create a factory as you describe....
public class CurrencyFactory
{
public static ICurrencyProvider GetCurrencyServiceProvider(string providerName)
{
return null;
}
}
then use standard dependency injection :-
public class CurrencyProcessor
{
private ICurrencyProvider _currencyProvider;
public CurrencyProcessor(ICurrencyProvider currencyProvider)
{
_currencyProvider = currencyProvider;
}
}
and then use like so
var p = new CurrencyProcessor(CurrencyFactory.GetCurrencyServiceProvider("bitcoin"));
then in your test mock it
var mock = new Mock<ICurrencyProvider>(). // mock stuff
Not sure if I understand it correct.
For me it sounds like you want to have 2 different Factories.
First create a Interface:
public interface ICurrencyProviderFactory
{
ICurrencyProvider Create()
}
Then create a Configuration Factory:
public class ConfigurationCurrencyProviderFactory : ICurrencyProviderFactory
{
public ConfigurationCurrencyProviderFactory(IConfigurationProvider configuration)
{
}
public ICurrencyProvider Create()
{
}
}
And then a UnitTest Factory:
public class UnitTestCurrencyProviderFactory : ICurrencyProviderFactory
{
public UnitTestCurrencyProviderFactory()
{
}
public ICurrencyProvider Create()
{
}
}
Your currency processor should look like this:
public CurrencyProcessor(ICurrencyProviderFactory factory)
{
_currencyProvider = factory.Create();
}
In your ServiceCollection or whereever you resolve your dependencies you should include the correct factory.
So for Production, you add the ConfigurationCurrencyProviderFactory, for UnitTest the UnitTestCurrencyProviderFactory. Your actual code then should depend on ICurrencyProviderFactory.
What you actually need to apply along with your factory is the Strategy Pattern
interface ICurrencyProvider {
//...members
}
public interface ICurrencyProviderStrategy {
string Name { get; }
ICurrencyProvider Create();
}
public interface ICurrencyProviderFactory {
ICurrencyProvider GetCurrencyServiceProvider(string providerName);
}
An implementation of the factory would depend on a collection of strategies to call upon to create the desired types.
public class CurrencyProviderFactory : ICurrencyProviderFactory {
private readonly IEnumerable<ICurrencyProviderStrategy> strategies;
public CurrencyProviderFactory(IEnumerable<ICurrencyProviderStrategy> strategies) {
this.strategies = strategies;
}
public ICurrencyProvider GetCurrencyServiceProvider(string providerName) {
var provider = strategies.FirstOrDefault(p => p.Name == providerName);
if (provider != null)
return provider.Create();
return null;
}
}
This would allow greater flexibility as any number of strategies can be injected.
Here is an example of a CurrencyLayerWrapper Strategy
public class CurrencyLayerWrapperProvider : ICurrencyProviderStrategy {
public string Name { get { return "CurrencyLayerAPI"; } }
public ICurrencyProvider Create() {
return new CurrencyLayerWrapper();
}
}
Is it possible to create a class under test with FakeItEasy, where all dependencies that are declared in the constructor are initialized automatically with fakes?
Imagine the class:
public class Inserting
{
public Inserting(
ITransactionService transactionService,
ISharedData sharedData)
{
TransactionService = transactionService;
SharedData = sharedData;
}
public ITransactionService TransactionService { get; }
public ISharedData SharedData { get; }
public void Enter()
{
TransactionService.StartTransaction();
}
}
Then I am creating all fake-objects in the test setup and construct my class under test with those fakes:
public class InsertingTest
{
private Inserting _inserting;
private ISharedData _fakeSharedData;
private ITransactionService _fakeTransactionService;
[SetUp]
public void SetUp()
{
_fakeTransactionService = A.Fake<ITransactionService>();
_fakeSharedData = A.Fake<ISharedData>();
_inserting = new Inserting(_fakeTransactionService, _fakeSharedData);
}
[Test]
public void TestEnter()
{
// Arrange
// Act
_inserting.Enter();
// Assert
A.CallTo(() => _fakeTransactionService.StartTransaction().MustHaveHappened();
}
}
But I saw in the Java-world, that when using Mockito and Dagger 2, you can do something like this:
public class PhoneDialer {
private Activity activity;
private PhoneCallListener phoneCallListener;
#Inject
public PhoneDialer(Activity activity, PhoneCallListener phoneCallListener) {
this.activity = activity;
this.phoneCallListener = phoneCallListener;
}
}
public class PhoneDialerTest {
#Rule
public MockitoRule mockitoRule = MockitoJUnit.rule();
#Mock
PhoneCallListener phoneCallListener;
#Mock
Activity activity;
#InjectMocks
PhoneDialer dialer;
#Test
public void test_dialer() throws Exception {
// Arrange
// Act
dialer.callNumber("abc");
// Assert
Mockito.verify(phoneCallListener, times(1)).startCall();
}
}
and the mocked classes are initialized automatically with fakes. Is there an equivalent procedure or function in C# with FakeItEasy?
I think you want something like
Automatically inject fakes in test fixture with FakeItEasy. You use [Fake] to mark fakes to inject and [UnderTest] to mark the production type to test.
We really should put this into the documentation.
Alternatively,
AutoFixture has an AutoFixture.AutoFakeItEasy module,
there's Autofac FakeItEasy integration, and also
Ninject FakeItEasy integration
I saw 'Automatically inject fakes in text fixture with FakeItEasy' and my initial reaction was surprise that it differed from my preconception, mainly because it needs 'intrusive' changes that attribute the test code... but perhaps that is an overreaction.
The FakeAttribute and UnderTestAttribute do force what is potentially a good structural constraint on your test (and system) design...
[FWLIW, before googling this, I had imagined the following:
containerBuilder.RegisterAsFakeCallingBaseType<SystemUnderTest>();
You can do something like this with Autofac's registration sources.
using Autofac;
using Autofac.Core;
using Autofac.Core.Activators.Delegate;
using Autofac.Core.Lifetime;
using Autofac.Core.Registration;
using FakeItEasy;
using Xunit;
public interface IDependOnSomething { }
public class IImplementThat : IDependOnSomething { }
public class CanIResolveIt
{
public CanIResolveIt(IDependOnSomething it)
{
}
}
public class FakeRegistrationSourceTest
{
[Fact]
public void BasicTest()
{
var container = new ContainerBuilder();
container.RegisterTypes<IImplementThat>().As<IDependOnSomething>();
container.RegisterSource(new FakeRegistrationSource<CanIResolveIt>());
var c = container.Build();
var theFake = c.Resolve<CanIResolveIt>();
Assert.NotNull(theFake);
}
}
public class FakeRegistrationSource<T> : IRegistrationSource
where T : class
{
public bool IsAdapterForIndividualComponents => false;
public IEnumerable<IComponentRegistration> RegistrationsFor(Service service, Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var swt = service as IServiceWithType;
if (swt == null || !typeof(T).IsAssignableFrom(swt.ServiceType)) // TODO: is this the right way around?
{
return Enumerable.Empty<IComponentRegistration>();
}
var registration = new ComponentRegistration(
Guid.NewGuid(),
new DelegateActivator(swt.ServiceType, (context, #params) =>
{
List<object> v = new List<object>();
foreach (ParameterInfo p in typeof(T).GetConstructors().Single().GetParameters())
{
v.Add(context.Resolve(p.ParameterType));
}
return A.Fake<T>(that => that.CallsBaseMethods().WithArgumentsForConstructor(v));
}),
new CurrentScopeLifetime(),
InstanceSharing.None,
InstanceOwnership.OwnedByLifetimeScope,
new[] { service },
new Dictionary<string, object>());
return new IComponentRegistration[] { registration };
}
}
Main advantage of this approach is that it knows how to instantiate fake objects subclassing classes with constructor parameters, and inheriting their default behavior, when they have a single constructor (choosing intelligently from multiple constructors would be an obvious challenge that I'm not going to tackle...)
An obvious drawback is explicit registration every time you want something faked. AutoFake and so on offer ways to overcome that with faking of just about everything by default, which might well be what you want... and you can override it if not.]
I have a ICommand interface and tasks that are using dependencies injected by constructor. Dependencies are using different constructors so they have to be resolved by the request itself. I want to tell my container how to resolve some dependencies in the specific context it's being resolved.
interface ICommand
{
string Do();
}
interface IUser
{
string Name { get; }
}
class Welcome : ICommand
{
IUser _user;
public Welcome(IUser user)
{
_user = user;
}
public string Do()
{
return "Hello, "+_user.Name;
}
}
class OAuthUser : IUser
{
// use remote service to get data
public OAuthUser (IOAuthService service, JsonWebToken token)
{
// to be implemented
}
}
class TemporaryTokenUser : IUser
{
// use sql to check if user has temporary token
public TemporaryTokenUser (IDbConnection db, string token)
{
// to be implemented
}
}
class UserPasswordUser : IUser
{
// try authenticating user with credentials
public UserPasswordUser (IAuthService svc, string user, string password)
{
// to be implemented
}
}
I've registered my interfaces and classes in LightInject:
var container = new LightInject.ServiceContainer();
container.Register<ICommand, Welcome>("welcome");
Now, I want to do something like this in my requests:
using (var scope = container.BeginScope())
{
// I need to tell my container how to resolve this dependency in case its needed
// but method below does not exist
scope.ResolverForScope<IUser>(()=>createIUser(request));
var command = container.GetInstance<ICommand>(command);
return command.Do();
}
What would be the correct way to do this in maintainable way with any DI container, considering that dependency chain might get quite long for complex methods?
EDIT
I made my use case more clear (changed classes implementing IUser).
static class ScopedContainerExtensions
{
class ScopedContainer
{
Dictionary<Type, object> factories = new Dictionary<Type,object>();
public void Register<T>(Func<T> factory)
where T: class
{
factories.Add(typeof(T), new Lazy<T>(factory));
}
public T Resolve<T>()
{
return ((Lazy<T>)factories[typeof(T)]).Value;
}
}
public static void UseScopedContainerFor<Service>(this IServiceContainer container)
{
if (!container.CanGetInstance(typeof(ScopedContainer), ""))
{
container.Register<ScopedContainer>(new PerScopeLifetime());
}
container.Register<Service>(sf=>sf.GetInstance<ScopedContainer>().Resolve<Service>());
}
public static void ResolverForCurrentScope<T>(this IServiceContainer container, Func<IServiceFactory, T> factory)
where T : class
{
var scope = container.ScopeManagerProvider.GetScopeManager().CurrentScope;
container.GetInstance<ScopedStorage>().Register<T>(() =>
{
var instance = factory(container);
var disposable = instance as IDisposable;
if (disposable != null)
scope.TrackInstance(disposable);
return instance;
});
}
Registration:
container.UseScopedContainerFor<IUser>();
Usage in scope:
container.ResolverForCurrentScope<IUser>(fac => fac.GetInstance<OAuthUserFactory>().Create(fac.GetInstance<IOAuthService>(), Request));
It might be developed via using the Factory pattern.
With this approach, you might be able to get an instance of the specific user with a Factory to provide instances for each concrete class.
Using explicit service registration:
var container = new LightInject.ServiceContainer();
//register your command passing a user instance
container.Register<ICommand>(factory => new Welcome(factory.GetUser<IUser>(request)));
using (var scope = container.BeginScope())
{
var command = (ICommand)container.GetInstance<ICommand>();
return command.Do();
}
I just referred to LightInject web page. There is a chapter called "Dependency Constructors" for further information. http://www.lightinject.net/#toc16
Hope it helps
Can anyone help?
I have a wpf app (shouldn't matter) and in the Onstart i have my bootstrap stuff.. Its like this..
// Create unity container my service and repository
container = new UnityContainer()
.RegisterType<ISecurityRepository, SecurityRepository>()
.RegisterType<ISecurityService, SecurityService>();
Basically ISecurityService expects me to pass in a ISecurityRepository, hence the above fails.
But i am little confused, do i have to create a new IsecurityRespository and then pass it in, this defeats the object doesn't it?
Is there anyway i say "pass into SecurityService the ISecurityRepository from the container", but it hasn't been built yet?
Any ideas?
You don't have to create instances first. It all just works. That's the magic of IoC Containers.
Example:
public interface ISecurityService { }
public interface ISecurityRepository { }
public class SecurityService : ISecurityService
{
public SecurityService(ISecurityRepository repository)
{
Console.WriteLine("SecurityService created");
Console.WriteLine("Repository is " + repository);
}
public override string ToString()
{
return "A SecurityService";
}
}
public class SecurityRepository : ISecurityRepository
{
public SecurityRepository()
{
Console.WriteLine("SecurityRepository created");
}
public override string ToString()
{
return "A SecurityRepository";
}
}
public class MyClassThatNeedsSecurity
{
public MyClassThatNeedsSecurity(ISecurityService security)
{
Console.WriteLine("My class has security: " + security);
}
}
class Program
{
static void Main()
{
using (IUnityContainer container = new UnityContainer())
{
container.RegisterType<ISecurityRepository, SecurityRepository>()
.RegisterType<ISecurityService, SecurityService>();
MyClassThatNeedsSecurity myClass =
container.Resolve<MyClassThatNeedsSecurity>();
}
}
}
This will print:
SecurityRepository created
SecurityService created
Repository is A SecurityRepository
My class has security: A SecurityService
You have a number of options, such as pre-creating your instances (as you showed in your follow-up post) or extending the lifetime of injected dependencies so that they're not recreated every time they're needed. But for the base case, this will work.
here is some more information. The constructor of my class is
public SecurityService(ISecurityRepository repository)
: base(repository)
{
}
After playing around a little bit, i managed to do the following but this causes me to create instances FIRST ... It seems to work.., but its an alternative.
// Create unity container my service and repository
ISecurityRepository securityRepository = new SecurityRepository();
ISecurityService securityService = new SecurityService(securityRepository);
container = new UnityContainer();
container.RegisterInstance<ISecurityRepository>(securityRepository);
container.RegisterInstance<ISecurityService>(securityService);