How Can I Resolve Other Dependencies within Ninject .OnActivation? - c#

I am using Ninject to set up bindings for a class which is an IObservable.
I have set up a rebind to ensure that the IObservable has it's IObserver subscribed as follows...
kernel.Rebind<IAddressRepository>().To<AddressRepository>().InRequestScope()
.OnActivation(repo => repo
.Subscribe(new SyncTrackerDataEventObserver<Address, AddressRepository>()));
This seems to work OK but it really isn't ideal. SyncTrackerDataEventObserver will, when it's more than a stub have dependencies of it's own. Then we end up with this...
kernel.Rebind<IAddressRepository>().To<AddressRepository>().InRequestScope()
.OnActivation(repo => repo
.Subscribe(new SyncTrackerDataEventObserver<Address, AddressRepository>(new SyncTrackerRepository(new SyncDataSource))));
Ouch!!
What I want to do is make use of the existing bindings at this point. I'd expect to be able to write something like this (but this is just made up..)
kernel.Rebind<IAddressRepository>().To<AddressRepository>().InRequestScope()
.OnActivation(repo => repo
.Subscribe(kernel.Resolve<ISyncTrackerDataEventObserver>()));
What is the correct way to achieve this without creating a hell of hard coded dependencies and breaking IoC paradigms?

This was quite straightforward when I figured out where to look. kernel.TryGet<> will get you the service type from the current bindings.
kernel.Rebind<IAddressRepository>().To<AddressRepository>().InBackgroundJobScope()
.OnActivation(repo => repo
.Subscribe(kernel.TryGet<SyncTrackerDataEventObserver<Address, AddressRepository>>()
?? throw new ObserverBindingException("Address")));
(where ObserverBindingException is a custom exception type I created just for this purpose).

Related

.NET: Subscribe to event, decoupled. IOC?

I am writing a service in .NET/C# that recieves updates on items.
When an item is updated, i want to do several actions, and more actions will come in the future. I want to decaouple the actions from the event through some commen pattern. My brain says IOC, but I am having a hard time finding what i seek.
Basically what I am thinking is having the controller that recieves the updated item, go through come config for actions that subscribes to the event and call them all. Surely there exists some lightweight, fast and easy to use framework for this, thats still up-to-date.
What would you recommend and why? (emphasis on easy to use and fast).
There is one pattern that uses DI-container (IoC, yes). There is a lot of DI-containers and I personally use Castle Windsor. But any container should do this trick.
For example, you can create such an interface:
public ISomeAction
{
void Execute(SomeArg arg);
}
And, when you need to call all the actions, you can use it like this:
var actions = container.ResolveAll<ISomeAction>();
foreach (var action in actions)
{
action.Execute(arg);
}
To "register" an action, you need to do something like this:
container.Register(Component.For<ISomeAction>().ImplementedBy<ConcreteAction());
You can use XML for this, if you want.
It's very flexible solution - you can use it in any part of your app. You can implement this "for future", even if you don't need to subscribe anything. If someone would add a lib to your project, he will be able to subscribe to your event by simply registering his implementation.
If you want to use .NET events, than Castle Windsor has an interesting facility:
https://github.com/castleproject/Windsor/blob/master/docs/event-wiring-facility.md
In case anyone needs it, heres is how to do it in StructureMap:
var container = new Container(_ =>
{
_.Scan(x =>
{
x.TheCallingAssembly();
x.WithDefaultConventions();
x.AddAllTypesOf<IUpdateAction>();
});
});
var actions = container.GetAllInstances<IUpdateAction>();
foreach (IUpdateAction action in actions)
{
action.Execute(updatedItem);
}

How to have NInject follow type hierarchy?

I am surprised that NInject does not follow the type hierarchy when looking for a binding.
Bind<ICollection<ICard>>().ToConstructor(/* .. */);
var Cards = IoC.Kernel.Get<IList<ICard>>();
In the above code, the Kernel.Get<..>() sends me an ActivationException because I haven't explicitely bound IList<ICard>. In other words, for NInject, an IList<ICard> is not an ICollection<ICard>. Sounds strange to me.
Of course I can remove the error by explicitely adding Bind<IList<ICard>>().To<..>(), but I don't understand why NInject doesn't follow type hierarchy by default. Am I missing something?
So, can somebody explain:
Why NInject forces me to be that specific in my bindings
How I can overcome this behaviour without adding a tedious list of bindings for every possible collection (unless you convince me that it is a very bad practice to do so)

How does one provide dummy data using MVVM light at design time when ViewModels are using constructor injection?

I ran into a strange problem yesterday. I built a makeshift viewmodel locator style system yesterday using ninject as its di container. I then tried to have it resolve a moq mock implementation of a data repository interface to feed into the viewmodels through constructor injection. But, I keep getting the following exception from moq at design time.
Error 2 Unable to cast object of type 'Castle.Proxies.IADEmployeeRepoProxy_1' to type 'MVVMSupport.TestHarness.Data.IADEmployeeRepo'. D:\Users\kicksagnome\Desktop\MVVMSupport\MVVMSupport.TestHarness\App.xaml 16 13 MVVMSupport.TestHarness
Mock<IADEmployeeRepo> repo = new Mock<IADEmployeeRepo>();
repo.Setup<List<ADEmployee>>(r => r.GetAllEmployees())
.Returns(new List<ADEmployee>() { new ADEmployee() { FirstName = "Ryan Butcher" } });
Bind<IADEmployeeRepo>().ToConstant(repo.Object); //Also tried Bind<IADEmployee>().ToMethod(context => repo.Object);
It runs fine the first load of the designer and fails every time design data is changed and I rebuild the solution.
I recognize this isn't how moq is meant to be used so the question is...
1.) Is there a way to fix this issue?
2) How should I be adding design time data?
Well, you have several options.
You could have different options in your View Model depending on "IsInDesignMode", and have your design data reside there. That would be your quick and dirty option.
A better option would be to have a DataService, and a Mock one (or DesignDataService), and in your ViewModelLocator, you'll use that in your "IsInDesignMode".
From there, just add whatever you need to mock to the Interface of the DataService, this service will be injected into your view model on construction, and you can then simple have something like:
MyData = DataService.GetData();
In the real data service, you'll fetch your data, and in the design/mock one, you can fake to your liking, having your design data displayed easily.
Let me know if you have any other questions, or need more code for the example.

Resolving context driven parameters with Autofac

I am trying to find a better way to resolve context-driven parameters using Autofac. Consider the following code :
builder.RegisterType<SqlDatabaseResourceFactory>().WithParameter("connectionStringKey", "MyConnectionStringKey").As<DatabaseResourceFactory>();
builder.RegisterType<ATypeRepository>().As<IATypeRepository>().PropertiesAutowired();
builder.RegisterType<BTypeRepository>().As<IBTypeRepository>().PropertiesAutowired();
builder.RegisterType<CTypeRepository>().As<ICTypeRepository>().PropertiesAutowired();
builder.RegisterType<DTypeRepository>().As<IDTypeRepository>().PropertiesAutowired();
In this case, each "Repository" has a property ResourceFactory, typed DatabaseResourceFactory, that has a local default (for compatibility with legacy code). This works great as long as all the types needing ResourceFactory injected use the same connection string.
If, say, C and D repositories needed a different connection string, though, this solution would no longer work. The best work-around I can think of is to use something like the following
builder.RegisterType<ATypeRepository>()
.As<IATypeRepository>()
.OnActivating(c => c.Instance.ResourceFactory = new SqlDatabaseResourceFactory("MyConnectionStringKey"));
But this now needs doing for each repository type registered, which seems overly repetitive and clunky. Is there a better solution to this type of problem. Is this problem an indication of some underlying architectural issue?
If, say, C and D repositories needed a different connection string,
If C and D need a different connection, they should get their own abstraction. For instance define a IBillingDatabaseResourceFactory and IShippingDatabaseResourceFactory. This resolves the ambiguity that's currently in your design and DI configuration.
You could use:
builder.Register(c => new CTypeRepository(new SqlDatabaseResourceFactory("C-connectionstring")).As<ICTypeRepository>().PropertiesAutowired();

Using Mock objects with Dictionary

I just started working with Unit Testing with NMock
I one my test cases involve adding an entry in a dictionary which is then passed to the unit being tested. I define the map as:
var item = new Mock<MyClass>().Object;
var myMap = new Dictionary<MyClass, IList<MyOtherClass>>
{
{ item, completionRequirement }
};
However when I do a myMap.ContainsKey(item) inside the unit being tested it returns false.
I am able to view a proxied item in the Dictionary on inspecting it. I am guessing that I need to do something else as well on the mocked item.(Most probably define .Equals(object o)).
My question is :
How do you define the Equals(object o) for the mocked item.
Or is there a different solution to the problem altogether.
You might want to mock the dictionary as well. That is, refactor to use IDictionary<MyClass,IList<MyOtherClass>, then pass in a mocked dictionary. You can then set up expectations so that it returns mocked objects as necessary.
It's also possible that you may not need to use a mock at all in this instance. It's not possible to tell from what you've given us, but I've often found that people new to mocking can sometimes forget that you can use the real objects as well if those objects don't have cascading dependencies. For example, you don't really need to mock a class that's just a simple container. Create one and use it, instead. Just something to think about.
The approach given at http://richardashworth.blogspot.com/2011/12/using-reflection-to-create-mock-objects.html is in Java, but presents another approach to this problem using Reflection.
I like the idea of setting up a 'fake' object along the lines of what tvanfosson is suggesting.
But if you want to do it with a mocking framework, I think all you need to do is setup an expectation for what item.Object should be. In Rhino Mocks the syntax would be something like:
var knownObject = "myKey";
var mock = MockRepository.GenerateStub<IMyClass>();
mock.Stub(x=>x.Object).Return(knownObject);
That said, I have no idea what the equivalent code would be in NMocks, but it shouldn't be hard to figure it out if you're working with it (you can always ask a question on the user group).
HTH

Categories