Reputation: 47377
In our mobile app (Xamarin), we register an instance of the current user for use with our Repository (every repository requires an instance of CurrentUser
).
When we start the app for the first time, we register the Guest User so that we can create our first records before the actual user logs in or registers.
public static UserModel GuestUserForRegistration()
{
return new UserModel
{
Id = Migration001.GuestUserId,
Email = Migration001.GuestEmail,
PasswordHash = Migration001.GuestPassword
};
}
_containerBuilder.RegisterInstance(GuestUserForRegistration());
After the app starts up, we have a single entry point where we resolve the MainPage
return Container.Resolve<MainPage>();
It's at this point that the object graph is built, and we use DI for everything (no service location).
After a user signs in / registers for the first time, we call the following method
public static IContainer Container;
public static void RegisterCurrentUser(UserModel userModel)
{
CurrentUser = userModel;
var builder = new ContainerBuilder();
builder.RegisterInstance(userModel);
builder.Update(Container);
}
This method is supposed to do two things.
The problem is that after the user signs in, if I put a break point in my Repository, the resolved user in the constructor is still guest.
Is this because the object graph has been completely built already using the GuestUser, and therefore the Repository has already been built before I ever updated the Container?
If so, is there a way around this?
Upvotes: 1
Views: 1230
Reputation: 8295
There's 2 ways you could solve this that don't require your application code to be aware of your container.
The first method, instead replacing the registered instance of UserModel
with a new instance, you'd just update the registered instances properties to the new values. This is probably the simplest, if your type is mutable and not overly complex.
This second method would be appropriate if updating the original UserModel
instance is undesirable or impossible. Basically, just add a layer of indirection:
// -------------------------
// add this class:
public class Changeable<T>
{
public T Value { get; set; }
}
// -------------------------
// set up registrations like so:
// register the default value like so
builder.RegisterInstance(
new Changeable<UserModel>
{
Value = new UserModel
{
Id = Migration001.GuestUserId,
Email = Migration001.GuestEmail,
PasswordHash = Migration001.GuestPassword
}
});
// register UserModel directly, which can be used by all the classes that don't
// need to change the instance
builder.Register(c => c.Resolve<Changeable<UserModel>>().Value);
Now your service classes can take a constructor parameter of either Changeable<UserModel>
or just UserModel
depending on whether they need to be able to change the instance or not, with no more direct reference to the container.
Upvotes: 1