Inject ViewModel and its property - c#

I have ViewModel in my Silverlight project
public class MainViewModel : BaseNotify, IMainViewModel
{
[Dependency("AccountID")]
public Guid AccountID { get; set; }
...
public MainViewModel()
{
if (AccountID != Guid.Empty)
{
PreSelectedAccount = new Account() { ID = AccountID };
SingleAccountMode = true;
}
}
....
}
I'm using Unity this way:
public static class IoC
{
static IoC()
{
Current = new UnityContainer();
Current.RegisterType<IMainViewModel, MainViewModel>();
}
public static UnityContainer Current { get; set; }
}
public partial class App : Application
{
[Dependency]
public IMainViewModel ViewModel { get; set; }
private void Application_Startup(object sender, StartupEventArgs e)
{
Guid accountId = "1234-5678-1234-5678-1234";
IoC.Current.BuildUp(this);
}
}
After calling BuildUp method,I have instance of MainViewModel in the App.ViewModel, but how I can set up Unity to inject also some value for MainViewModel.AccountId property value during BuildUp?

You need to resolve/buildup with an override:
IoC.Current.BuildUp(this, new PropertyOverride("AccountID", accountId));

Your code looks like you are using the ServiceLocator anti-pattern. A pattern like constructor injection is most often preferable.
Another question: Why do you hook up your MainViewModel with your App class? Usually you would use it as the DataContext for your MainView.
And it is not common to inject primitive values like Guids using a DI container.

As #nemesv mention you might need to change your BuildUp method call, but doing so, I don't think you can achieve what you need.
The problem is first instance of the MainViewModel is created and then AccountId is passed into it, so your logic in the constructor is never true, e.g.
if(AccountID != Guid.Empty)
is never true. Alternativly you can add this logic to Setter of the AccountID property, something inline with this:
public Guid AccountId {
get { return _accountId; }
set {
_accountId = value;
OnAccountIdChanged();
}
}
protected virtual void OnAccountIdChanged() {
if(AccountId != Guid.Empty) {
//do your thing here
}
}

Related

Unity Container resolve calling same parameterized constructor twice

I'm using a unity container and I'm trying to resolve by passing the object to the parameterized constructor, I noticed the same constructor is called twice, the first time it takes appropriate values, and not sure why it is calling again and it overrides with a blank object, can someone help me what is happening over here, not able to solve it.
//////////////////////////////////////////////////////////////////////
if (container == null)
{
container = new UnityContainer().AddExtension(new Diagnostic());
container.RegisterType<ISubscribeService,OOrderProc.Common.SubscribeService.SubscribeService>();
container.RegisterType<IBaseOrderProcessing, BaseSubscribe>("Subscribe");
}
SubscribeDetails m = new SubscribeDetails();
m.SubscribeType = SubscribeType.ACTIVATE;
m.SubscribeName = "TEST";
var b = container.Resolve<IBaseOrderProcessing>("Subscribe",new DependencyOverride<BaseSubscribe>(new OOrderProc.Common.SubscribeService.SubscribeService(m)));
//////////////////////////////////////////////////////////////////////
public interface IBaseOrderProcessing
{
void ProcessOrder();
}
public interface ISubscribeService
{
SubscribeType SubscribeType { get; set; }
void ActivateSubscribe();
void UpgradeSubscribe();
}
// Strategy Pattern 1 => Subscribe is one of the "if" condition
public class BaseSubscribe : IBaseOrderProcessing
{
private ISubscribeService _SubscribeService = null;
public BaseSubscribe(ISubscribeService SubscribeService)
{
_SubscribeService = SubscribeService;
}
public void ProcessOrder()
{
if (_SubscribeService.SubscribeType == SubscribeType.ACTIVATE)
_SubscribeService.ActivateSubscription();
if (_SubscribeService.SubscribeType == SubscribeType.UPGRADE)
_SubscribeService.UpgradeSubscription();
}
}
// Writing another class to simplify is correct ?????
public class SubscribeService : ISubscribeService
{
private SubscribeDetails _Subscribedetails = null;
public SubscribeType SubscribeType { get; set; }
public SubscribeService(SubscribeDetails Subscribedetails)
{
_Subscribedetails = Subscribedetails;
SubscribeType = Subscribedetails.SubscribeType;
}
public void ActivateSubscription()
{
// Code to save the Subscribe details in the database
Console.WriteLine($"\n\nSubscribe {_Subscribedetails.SubscribeId} for {_Subscribedetails.SubscribeName} activated for order Id: {_Subscribedetails.OrderId}" +
$" from {_Subscribedetails.SubscribeStartDate} to {_Subscribedetails.SubscribeEndDate}");
}
public void UpgradeSubscription()
{
// Code to upgrade the Subscribe details in the database
Console.WriteLine($"\n\nSubscribe {_Subscribedetails.SubscribeId} for {_Subscribedetails.SubscribeName} upgraded for order Id: {_Subscribedetails.OrderId}" +
$" from {_Subscribedetails.SubscribeStartDate} to {_Subscribedetails.SubscribeEndDate}");
}
}
I resolved using below code:
container.RegisterType<IBaseOrderProcessing, BaseSubscribe>("Subscribe", new InjectionConstructor(new OOrderProc.Common.SubscribeService.SubscribeService((SubscribeDetails)obj)));
return container.Resolve<IBaseOrderProcessing>("Subscribe");

How to change value in one class if value changes in another

Let's say I have a parameter in my ViewModel:
public string ChosenQualityParameter
{
get => DefectModel.SelectedQualDefectParameters?.Name ?? "Не выбран параметр";
}
and I have a class DefectModel with parameter SelectedQualDefectParameters.Name in it. I want to change the UI binded to ChosenQualityParameter, when theName parameter changes too.
But I don't know how to do this properly. Any suggestions? Thanks in advance.
You might define your ViewModel class like this:
public class ViewModel
{
private DefectModel _defectModel;
public ViewModel(DefectModel defectModel)
{
_defectModel = defectModel;
}
public string ChosenQualityParameter
{
get => _defectModel.SelectedQualDefectParameters?.Name ?? "Не выбран параметр";
}
}
I personally do not like such dependencies in viewmodels, but it might get the job done here. It seems to work in a console application anyway:
using System;
public class Parameters
{
public string Name { get; set; }
}
public class DefectModel
{
public Parameters SelectedQualDefectParameters { get; set; }
}
public class ViewModel
{
private DefectModel _defectModel;
public ViewModel(DefectModel defectModel)
{
_defectModel = defectModel;
}
public string ChosenQualityParameter
{
get => _defectModel.SelectedQualDefectParameters?.Name ?? "Не выбран параметр";
}
}
class Program
{
static void Main()
{
var defectModel = new DefectModel
{
SelectedQualDefectParameters = new Parameters
{
Name = "test"
}
};
var viewModel = new ViewModel(defectModel);
Console.WriteLine(viewModel.ChosenQualityParameter);
defectModel.SelectedQualDefectParameters.Name = "changed";
Console.WriteLine(viewModel.ChosenQualityParameter);
Console.ReadKey();
}
}
Thanks to #Knoop and #BartHofland, I've solved my issue by using INotifyPropertyChanged in my DefectModel and SelectedQualDefectParameters classes.
For setting ChosenQualityParameter I used MessagingCenter to send new value.

I want to implement singleton using DI and Unity [duplicate]

I'm new to Unity and am trying to write some Unity logic which initialises and register/resolves a singleton instance of the Email object so that it can be used across several other objects, one example below being OperationEntity.
So when it's registered it populates the Email singleton with some values from a config file, then whenever an instance of OperationEntity is created (in my case it's being deserialized) it uses that same Email singleton. So all my client logic needs to do is deserialize OperationEntity and call PerformAction() - with the email instance taken care of by Unity.
public interface IEmail
{
string FromName { get; set; }
string FromEmailAddress { get; set; }
}
public class Email : IEmail
{
public string FromName { get; set; }
public string FromEmailAddress { get; set; }
public Email(string fromName, string fromEmailAddress)
{
FromName = fromName;
FromEmailAddress = fromEmailAddress;
}
}
public class OperationEntity
{
private readonly IEmail _email;
public int OperationId { get; set; }
public string OperationName { get; set; }
public string ToAddress { get; set; }
public OperationEntity(IEmail email)
{
_email = email;
}
public void PerformAction()
{
_email.ToAddress = ToAddress;
_email.Body = "Some email body";
_email.Deliver();
}
}
Any help would be appreciated in getting this Unity code to work
public static void Register(IUnityContainer container)
{
container
.RegisterType<IEmail, Email>(
new InjectionFactory(c => new Email(
"To Name",
"to#email.com")));
var email = container.Resolve<IEmail>();
container.RegisterType<OperationEntity>(
"email", new ContainerControlledLifetimeManager(),
new InjectionConstructor(email));
}
First, you need a proper lifetime manager the ContainerControlledLifetimeManager is for singletons.
For custom initialization, you could probably use InjectionFactory
This lets you write any code which initializes the entity.
Edit1: this should help
public static void Register(IUnityContainer container)
{
container
.RegisterType<IEmail, Email>(
new ContainerControlledLifetimeManager(),
new InjectionFactory(c => new Email(
"To Name",
"to#email.com")));
}
and then
var opEntity = container.Resolve<OperationEntity>();
Edit2: To support serialization, you'd have to rebuild dependencies after you deserialize:
public class OperationEntity
{
// make it public and mark as dependency
[Dependency]
public IEmail _email { get; set;}
}
and then
OperationEntity entity = somehowdeserializeit;
// let unity rebuild your dependencies
container.BuildUp( entity );
You could use:
container.RegisterType<IEmail, Email>(new ContainerControlledLifetimeManager());
If IEmail is a singleton with no dependencies (just custom arguments), you can new it up yourself:
container.RegisterInstance<IEmail>(new Email("To Name", "to#email.com"));
That will register the supplied instance as a singleton for the container.
Then you just resolve the service:
container.Resolve<OperationEntity>();
And because you are resolving a concrete type, there is no registration required. Nevertheless, if you would like that service to also be a singleton, you can register it using ContainerControlledLifetimeManager and then all calls to resolve (or when injecting it as a dependency to another class) will return the same instance:
container.RegisterType<OperationEntity>(new ContainerControlledLifetimeManager());
You can, for example, use this code:
public class example : MonoBehaviour
{
public static example instance;
public void Start()
{
(!instance)
instance = this;
}
}
You could implement your own singleton class and extend any class form it.
public class MyClass : MonoBehaviour {
private static MyClass _instance;
public static MyClass Instance { get { return _instance; } }
private void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(this.gameObject);
} else {
_instance = this;
}
}
}

Is it possible to create a stub for a creation of a concrete class?

I have a service class, it creates a new concrete PropertyClass, before doing action. I'm trying to test if DoSomething() was run.
Is it possible to create stud and control the returned Property value to a mock object?
public class ServiceClass
{
public PropertyClass Property {set; get;}
public void Action()
{
Property = new PropertyClass();
Property.DoSomething();
}
}
[Test] // This test does not work.
public class Action_Test
{
var service = new ServiceClass();
var mockPropertyClass = MockRepository.GenerateMock<IPropertyClass>();
service.Property.Stub(x=> new PropertyClass()).Return(mockPropertyClass);
service.Action();
service.Property.AssertWasCalled(x => x.DoSomething());
}
No. But you could easily mitigate this problem with factory design pattern. Consider:
public class ServiceClass
{
private readonly IPropertyClassFactory factory;
public PropertyClass Property { get; private set; }
public ServiceClass(IPropertyClassFactory factory)
{
this.factory = factory;
}
public void Action()
{
Property = factory.CreateInstance();
Property.DoSomething();
}
}
In test you create mocked factory which returns mocked object. Like this:
[Test]
public class Action_Test
{
var factoryMock = MockRepository.GenerateMock<IPropertyClassFactory>();
var propertyMock = MockRepository.GenerateMock<IPropertyClass>();
factoryMock.Stub(f => f.CreateInstance()).Returns(propertyMock);
var service = new ServiceClass(factoryMock);
service.Action();
propertyMock.AssertWasCalled(x => x.DoSomething());
}
Note that when factory is this simple, you might just as well use Func<IPropertyClass> instead of creating extra class/interface pair.
Your Action method is creating its own instance of PropertyClass which is overwriting your stub.
public void Action()
{
if (Property == null)
Property = new PropertyClass();
Property.DoSomething();
}
A nice way around having to check each time you use Property property, would be to assign the property in the constructor.
public ServiceClass() {
Property = new PropertyClass();
}
Then the Action method would just be:
public void Action()
{
Property.DoSomething();
}

Unity IoC and Static method

What is the best way to handle a situation where you're using IoC but there is a static method in it along with the other methods like the following:
public partial class ShoppingCart
{
private IDatabaseFactory _storeDB;
public ShoppingCart(IDatabaseFactory storeDB)
{
_storeDB = storeDB;
}
private string ShoppingCartId { get; set; }
public static ShoppingCart GetCart(HttpContextBase context)
{
var cart = new ShoppingCart(WHATGOESHERE?);
cart.ShoppingCartId = cart.GetCartId(context);
return cart;
}
public int OtherMethod()
{
...
}
}
The static GetCart method is an Ambient Context. It's a bad idea, especially to have such a method at the level of your domain model. Try refactoring it to an abstract factory:
public interface IShoppingCartFactory
{
ShoppingCart GetCartForCurrentUser();
}
You can inject the IShoppingCartFactory in services that need it (but not in your entities, it's better to keep your entities clean). Now you can define an implementation and register it in your IoC configuration. Here's an example of such an implementation:
public class HttpShoppingCartFactory : IShoppingCartFactory
{
private readonly IShoppingUnitOfWorkFactory uowFactory;
public HttpShoppingCartFactory(
IShoppingUnitOfWorkFactory uowFactory)
{
this.uowFactory = uowFactory;
}
public ShoppingCart GetCartForCurrentUser()
{
int userId = (int)HttpContext.Current.Session["userId"];
using (var unitOfWork = this.uowFactory.CreateNew())
{
return unitOfWork.ShoppingCards
.FirstOrDefault(c => c.User.Id == userId);
}
}
}
It would be even better to separate the getting the user context from the shopping card factory. For instance, you yould inject a IUserContextFactory in the shopping card factory, making it independant on ASP.NET.
IMO you should refactor it, making it to look like this:
public class ShoppingCartService {
private readonly IDatabaseFactory _storeDB;
public ShoppingCartService(IDatabaseFactory storeDB) {
_storeDB = storeDB
}
public ShoppingCart GetCart(IdType cartId)
{
var cart = new ShoppingCart(_storeDB);
cart.ShoppingCartId = cartId;
return cart;
}
}
public partial class ShoppingCart
{
private IDatabaseFactory _storeDB;
public ShoppingCart(IDatabaseFactory storeDB)
{
_storeDB = storeDB;
}
private string ShoppingCartId { get; set; }
public int OtherMethod()
{
...
}
}
This way, you are moving responsibility to get the current shopping cart from a static method to a service class you can inject in the presentation layer.

Categories

Resources