简体   繁体   中英

How to change the dependency at runtime using simple injector

I am new to simple injector. I have data access layer that has dependency on Force Client. I have register the ForceClient dependency. I want to replace the default value of ForceClient once user login into the application.

Please let me know, how i can change the default values at run time.

Ioc.ServiceContainer.Register(() => new ForceClient(
    "test",
    "test",
    "test"));

Here is the complete detail about the requirement. I have DAL in our Xamarin project that retrieve data from sales force using Developerforce.Force apis. I am writing unit test cases using MOQ to test the DAL.

DAL Code.

public CustomerRepository(IForceClient client)
{
    _client = client;                       
}

public async Task<long> GetTotalContacts()
{
    string totalContactCountQry = "some query"

    var customerCount =  await _client.QueryAsync<ContactsTotal>(totalContactCountQry);
    var firstOrDefault = customerCount.Records.FirstOrDefault();

    return firstOrDefault != null ? firstOrDefault.Total : 0;
}

Unit Test Case Code.

[SetUp]
public void Init()
{
    forceClientMock = new Mock<IForceClient>();
    forceClientMock.Setup(x => x.ForceClient(It.IsAny<string>(), 
        It.IsAny<string>(), It.IsAny<string>(), It.IsAny<HttpClient>()))
        .Return(new ForceClient(It.IsAny<string>(), It.IsAny<string>(), 
            It.IsAny<string>(), It.IsAny<HttpClient>()));              
    forceClientMock.Setup(x => x.QueryAsync<ContactsTotal>(It.IsAny<string>()))
        .ReturnsAsync(new QueryResult<ContactsTotal>());
    forceClientMock.Setup(x => x.QueryAsync<ContactsTotal>(It.IsAny<string>()))
        .ReturnsAsync(new QueryResult<ContactsTotal>() { Records=new List<ContactsTotal>() });            
}

[Test]
public void GetTotalContacts()
{              
    ICustomerRepository customerRepostory = new CustomerRepository(forceClientMock.Object);
    Assert.AreEqual(customerRepostory.GetTotalContacts().Result,0);
}

Simple Injector Registry on application initialization

container.Register<IForceClient>((() => new ForceClient(
    UserState.Current.ApiBaseUrl,
    UserState.Current.AuthToken.AccessToken,
    UserState.Current.ApiVersion)), Lifestyle.Transient);

The instance of ForceClient that i am creating during the registry is being created with all default valued of UserState. The actual value gets assigned once user login into the application.

I except ForceClient instance to have the updated value after login to access the sales force to retrieve the data but the program is giving error on below line DAL

var customerCount =  await _client.QueryAsync<ContactsTotal>(totalContactCountQry);

The reason is that the forceClient still contain default values. How can i make sure that the FoceClient instance get created after login to use the actual value of UserState

You can accomplish what you want by using Func<T> .

Rather than IForceClient in your classe, you can inject a Func<IForceClient> :

public CustomerRepository(Func<IForceClient> clientFunc)
{
    _clientFunc = clientFunc;
}

public async Task<long> GetTotalContacts()
{
    string totalContactCountQry = "some query"

    // calling _clientFunc() will provide you a new instance of IForceClient
    var customerCount =  await _clientFunc().QueryAsync<ContactsTotal>(totalContactCountQry);
    var firstOrDefault = customerCount.Records.FirstOrDefault();

    return firstOrDefault != null ? firstOrDefault.Total : 0;
}

The simple injector registration:

// Your function
Func<IForceClient> fonceClientFunc = () => new ForceClient(
    UserState.Current.ApiBaseUrl,
    UserState.Current.AuthToken.AccessToken,
    UserState.Current.ApiVersion);

// the registration
container.Register<Func<IForceClient>>( () => fonceClientFunc, Lifestyle.Transient);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM