Search code examples
c#dependency-injectiondryioc

Inject property with value from another property of another registered object?


I'm not so sure that DryIoc is worth my time. It looks like lightweight and supported well in cross-platform environment (with Xamarin). But I feel a bit difficult working with it (in term of exploring everything myself).

The DryIoc community is also not very large (and by reading through some answers about DryIoc, I recognized that looks like there is only the author jumping in and giving the answers). Here is my problem as mentioned in the title. Suppose I have 2 ViewModel classes, the second has a property which should always match (mapped) with a property of the first, like this:

public class ParentViewModel {
}
public class FirstViewModel {
   public FirstViewModel(ParentViewModel parent){
   }
   public string A {
      //...
   }
}
public class SecondViewModel {
   public SecondViewModel(ParentViewModel parent){
   }
   public string A {
      //...
   }
}

Now I can use dryioc to register singleton for both ViewModels BUT for the second one, I also need to inject the property A with value from the first's property A as well.

container.Register<ParentViewModel>();
container.Register<FirstViewModel>(reuse: Reuse.Singleton, made: Made.Of(() => new FirstViewModel(Arg.Of<ParentViewModel>())));
container.Register<SecondViewModel>(reuse: Reuse.Singleton, made: Made.Of(() => new SecondViewModel(Arg.Of<ParentViewModel>())));

So as you can see the first registration should be fine because no property dependency is required. However the second one should have its A property depend on the A of the first one.

Really I cannot explore this myself. Injecting properties of some registered type is fine (and at least I know how to do that), but here the injected value is another property of some registered type.


Solution

  • Here is the straightforward way (but may be not the best one) to achieve that:

    using System;
    using DryIoc;
    
    public class Program
    {
        public static void Main()
        {
            var container = new Container();
    
            container.Register<ParentViewModel>();
    
            container.Register<FirstViewModel>(Reuse.Singleton);
    
            container.Register<SecondViewModel>(Reuse.Singleton, 
                made: PropertiesAndFields.Of.Name("A", r => r.Container.Resolve<FirstViewModel>().A));
    
            var firstVM = container.Resolve<FirstViewModel>();
            firstVM.A = "blah";
    
            var secondVM = container.Resolve<SecondViewModel>();
    
            Console.WriteLine(secondVM.A); // should output "blah"
        }
    
        public class ParentViewModel {
        }
    
        public class FirstViewModel {
           public FirstViewModel(ParentViewModel parent) { }
           public string A { get; set; }
        }
    
        public class SecondViewModel {
           public SecondViewModel(ParentViewModel parent) {}
           public string A { get; set; }
        }
    }
    

    In my opinion, the better and more simple way will the inversion of control: creating the A outside of both VMs and then injecting them into both.