How to pass in an object when using an IoC container - c#

I am doing a project in ASP.NET MVC in which I want to implement an IoC container. I am new to IoC containers and have been searching to find a solution to my problem, but so far to no avail.
The problem is dat data is distributed across various databases. Once a user is logged in, the database for the user is retrieved from an authorization database and then set in the user session. That user session is passed on to the services and repositories when they are constructed, so they can use it when they need it to access the database.
A typical bare stripped service (without interfaces and ioc) looks like this:
private CompetitionRepository _CompetitionRepo;
public CompetitionService(DataContext dataContext)
: this (new CompetitionRepository(dataContext))
{ }
public CompetitionService(CompetitionRepository competitionRepo)
{
this._CompetitionRepo = competitionRepo;
}
The "DataContext" contains a couple of properties with which the correct database is selected for the session. Because the Services and Repositories don't have access to the session itself (which is outside of their scope) they need this object.
My question is, how can I set something like this up in IoC (doesn't matter which container, I just want to know the general idea). As far as I can see, most containers do not allow objects to be passed in? Or is the design fundamentally flawed?

As far as I can see, most containers
do not allow objects to be passed in?
You can't be looking far then ;) Most IoC containers that I know have the ability to do this. You need to register an instance of an object based on its type. How and when that object is constructed is probably a deeper question than the one you've asked. However, to get to the point, you can do something like this with the Unity container:
DataContext context = ..... ;
container.RegisterInstance(context);
Each time you create an instance of a class that requires a DataContext, you'll get the one you've registered. If the type you want to associate the instance with is different, you can force it like so:
container.RegisterInstance<IDataContext>(context);
For more information, take a look here.

Related

Avoid a global state

Imagine some SOA. We have a few different services, of which the OperationContext is extended by some SecureOperationContext which makes sure certain security demands are met.
Assume furthermore that sometimes we might need to know a certain property from this SecureOperationContext somewhere else, in a place where there is and won't be this SecureOperationContext. For example a username for some sort of logging purpose.
Currently we're using something that looks and smells plain dirty. The fat's dripping of in my opionion.
Now, in some 'Common' library, there is a class defined with a ThreadStatic property: Username. I guess you can catch my drift: the security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This thing bugs me, but on the other hand what else to do? I was thinking about creating a method that takes a string as parameter to handle this, but then all my methods need to still read that username property, which is non-dry.
So on one hand, this way everything is handled on the background, but I'm not just quite happy having to maintain some (global) class just to achieve this.
Any tips?
I'm not sure how to put it in less abstract terms, but here goes (in pseudo).
public WebService
{
public Save(Car car)
{
// Some SecurityCOntext is known here, this holds top secret info,
// like the username
// and sets this into the golbal helper class UserNameManagemer
// car has for example a CreatedDate property (from an Interface),
//but I don't want handle do this propertyin every Create method can handled in some general piecei of code.
efcontainer.AddObjcect(car)
e.SaveChanges() ->
//Now savechanges will check the objects in the ObjectSatateManager
//and sets the apppriopriate property via the global thing.
}
}
Now what to do to rid myself of this global variable!. Passing a username to SaveChanges is undesirable ass well, since we'd then still have to manually repat this for everything, which blows.
Encapsulate the global property in a service. Define an interface for that service. Now, depend on that interface everywhere you need the data by having a constructor parameter of that type.
This is called dependency injection and is a very important concept when you want to avoid problems as the one you currently have. A dependency injection container such as Autofac can help if you have a big application, but is not strictly required.
The most important thing is to understand dependency injection and have a well-defined composition root, no matter whether you use a DI container or do it yourself.
The security stuff sets this static global variable and lo and behold we have it available for logging puproses.
This sounds like the data is determined dynamically. Note that you can still use a service to track the value. That service also knows whether the value is available or not. This way, you can better manage the temporal coupling that you have at the moment.
Edit: You can further improve the design by creating the client objects through a factory. That factory can ensure that the value is available, so it couples the lifetime of the client objects to the availability of the value. This way, you are sure to always act in a context where the value can be safely accessed.

Proper way to communicate/pass values between viewmodels?

I know there's a lot of questions on the topic and I understand how to do it but I need some help on the design of my architecture. I'm using the Simple MVVM Toolkit.
Architecture
I have a ShellVM which is the main VM for my app. It dishes out navigation and props that my main view binds to.
Then I have a ManageVM that does all the grit work for managing the client, stores, imports, exports etc. It also handles navigation of all my management views.
Then I have an ImportVM that fleshes out the importing of data.
I also have a static PageValues dictionary that stores pages and specific properties and values that should be retained when switching views. It also stores any 'global' properties that is used throughout certain VMs.
I'm using Messaging to pass data between the VMs. The validation and prompts (using dialogs) of the PageValues data is controlled in my ManageVM. I placed it here as I feel my ManageVM should handle all 'management' like setting the client and store. Setting the actual values is done by sending a message to the ShellVM that handles this.
The ShellVM handles the CRUD of the PageValues. So in other words, if any VM gets or sets a global/shell-wide property, it does so by means of messaging to the ShellVM. The ShellVM then sends the message/result back to whichever VM requested it.
Question
This feels very spaghetti-like. I've got a ManageVM that does the loading and validations on PageValues that are actually CRUD'ed in the ShellVM.
Am I on the right track or is there any other suggestion I can try to make this feel a bit cleaner?
Thanks for reading.
Edit
What I'm trying to achieve is to have a container that holds values (ie client and store) that could be accessible from multiple VMs. A bonus is to have each page's/view's values in this container too. Then on showing of the view, it will grab its values from the container and populate the view.
You said
if any VM gets or sets a global/shell-wide property, it does so by
means of messaging to the ShellVM
I propose an interface based approach instead of message passing for this purpose. ViewModels passing messages is for view models to communicate,not for setting a global state. If there is a global state of the application,it is better handled through a dedicated service, IMO.
public interface IApplicationService
{
//your applcation methods here
}
public class ApplicationService:IApplicationService
{
}
public class ManageVM
{
public ManageVM(IApplicationService){}
}
public class ShellVM
{
public ShellVM(IApplicationService){}
}
public class SomeOtherVM
{
public SomeOtherVM(IApplicationService){}
}
Yes, this does sound rather messy. You need to try and isolate areas of functionality into their own VMs so they are not dependent on one another.
One of the tricks I use to do this is to try and imagine that I suddenly need to copy a blob of functionality (say one of your pageviews) into another application. How easy would it be? Would it be a case of just copying one VM and injecting a few dependencies? Or is the VM impossibly coupled to the rest of the app?
It's a bit difficult to give advice without knowing exactly what your app is doing, but really you want each PageVM to be in charge of it's own validation, and CRUD. Or, if the data is shared between many pages, then you need to pass in some kind of repository than the PageVMs can query for data. If validation logic is specific to some data, then put it on the model itself and just leave the presentation of that validation to the VM.
For global settings, I tend to pass around a settings object rather than using messaging.
Have a read up on inversion of control, and dependency injection. These can help you to keep objects loosely coupled because you can see exactly what other things your object is depending upon by looking at the constructor. If you are passing in half the application then it can serve as a warning alarm to try and reduce the coupling.

Inject different classes that implement the same interface using Ninject

I am implementing the builder design pattern to construct different kinds of graph objects to be displayed on a WPF UI. I am using Ninject as my IOC container. However, I am trying to find an elegant extendable solution.
I have a ChartDirector object that takes a IChartBuilder as a dependency. I also have TemperatureChartBuilder and ThresholdChartBuilder that implement IChartBuilder. I want to inject either TemperatureChartBuilder OR ThresholdChartBuilder to ChartDirector depending on an event that is fired or depending on a client call. I have illustrated my problem below in code.
// ChartDirector also depends on this
kernel.Bind<IExample>().To<Example>();
// when called in Method X...
kernel.Bind<IChartBuilder>().To<TemperatureChartBuilder>();
// when called in Method Y...
kernel.Bind<IChartBuilder>().To<ThresholdChartBuilder();
// TemperatureChartBuilder is a dependency of ChartDirector, need a way to dynamically
// allocate which binding to use.
var director = kernel.Get<ChartDirector>();
// without Ninject I would do
var director = new ChartDirector(new TemperatureChartBuilder);
// or
var director = new ChartDirector(new ThresholdChartBuilder);
EDIT:
Coupled with Gary's answer, and noting a slight edit that ChartDirector has another dependency, I now want to do something like this:
var director = kernel.Get<ChartDirector>().WithConstructorArgument(kernel.Get<IChartBuilder>("TemperatureChart"));
Is something like this possible?
If you're just planning to use service location, as in your examples, then named bindings work fine, as per Garys answer.
A better approach, however, is to use constructor injection, and use attributes. For exampl, from the ninject wiki:
Bind<IWeapon>().To<Shuriken>().Named("Strong");
Bind<IWeapon>().To<Dagger>().Named("Weak");
...
class WeakAttack {
readonly IWeapon _weapon;
public([Named("Weak")] IWeapon weakWeapon)
_weapon = weakWeapon;
}
public void Attack(string victim){
Console.WriteLine(_weapon.Hit(victim));
}
}
Based on your comment to Gary, you're (strangely enough) stumbling into territory similar to what I asked a question about a few hours ago. See Remo's answer here: Using WithConstructorArgument and creating bound type
You would use When condition to define when to create the correct instance.
I would suggest using Contextual bindings (named bindings specifically) to accomplish this. That way you can do something like:
// called on app init
kernel.Bind<IChartBuilder>().To<TemperatureChartBuilder>().Named("TempChartBuilder");
kernel.Bind<IChartBuilder>().To<ThresholdChartBuilder().Named("ThreshChartBuilder");
// method X/Y could both call method Z that grabs the correct chart director
var director = new ChartDirector(kernel.Get<IChartBuilder>("TempChartBuilder"));
Where "TempChartBuilder" could be a variable that tells ninject which binding to resolve. So rather binding on the fly you would resolve on the fly but all binding could be defined up front. Typically IOC containers are stored at the application domain level and only need to be defined once. There may be specific cases where you need to bind dynamically but those should be rare.
More info on contextual bindings: https://github.com/ninject/ninject/wiki/Contextual-Binding

.Net Application-wide variables

I'm fairly new to .Net... I have several queries which will execute when the application loads. I want these queries to store the data in an object (a dataset?) which is accessible throughout the application. Should I be using a singleton class? How can a User Control within my application reference public variables in the main application code?
I guess I haven't found a good resource on how / where to store application variables and how to reference them when I need to populate a ListBox, DataGridView, etc.
As a background I'm most familiar with developing using Flex Builder 3, sorry for the vague question... I'm having a problem locating a good reference on the topic (not just populating a Control, but storing the data at an application level and referencing it from anywhere within the app).
Edit: This is for programming a windows forms application using C#
Sounds like you're using ASP.NET, in which case Application State (MSDN) will allow you to store and retrieve application-wide data that can be accessed from anywhere in the application.
More here:
How to: Save Values in Application State
How to: Read Values from Application State
If you're writing a desktop app, you should create a static class that contains your application wide data, e.g:
public static class ApplicationSettings
{
public static string InstallDirectory { get { ... } set { ... } };
public static DataSet SomeDataSet { get { ... } set { ... } };
static ApplicationSettings()
{
// ... initialize or load settings here
}
}
A singleton isn't necessary here, but if you do require lazy initialization and thread satefy you might want to take that route.
You could store the information in a App.config file and use the AppSettingsReader class to access the data.
EDIT: Seeing that you don't want to query the information multiple times, you could use a Singleton to access and cache the data.
Presumably your objects will be required as long as the application's main form is open. If so, simply store them as properties of the form.
Singletons are bad, m'kay? ;)
Or, more to the point, global data (especially mutable global data) is generally not a good thing. It makes classes difficult to test and debug. Small scope is good scope.
One option is to look at an IoC Container library (aka a DI framework).
IoC = Inversion of Control
DI = Dependency Injection (or Inversion)
Basically you can set up constructors on your classes that need access to the global data and add a parameter of your "singleton" type - except it's not a singleton, just a Plain Old Object (or interface). Then you tell the Container that your "global data" class has a long lifespan, and use the Container to create your other objects. You won't use the "new" keyword much anymore. The benefit is that the Container will automagically wire everything up for you, creating one and only one instance of the global class and injecting it in to all of the other constructed objects.
Here's an (incomplete) list of the libraries/frameworks for .NET:
IoC Container Benchmark
Ninject's another one. I use Unity, but that doesn't mean it's the best for you.
Here's another list:
http://elegantcode.com/2009/01/07/ioc-libraries-compared/

Inversion of control for your Inversion of control container?

I've recently had to update a relatively large control library that uses Ninject 1.0 to Ninject 2.0 to help resolve some issues I had with 1.0. The update has gone well and I think Ninject 2.0 is a lot quicker.
However to try and avoid this problem in the future I have created my own interface for injecting fields and properties (which will essentially call methods on the IOC container I wish to use within the current web application). So now my control library is independant of any particular IOC container which will speed up any changes in that area in the future.
I was wondering has anyone else has done the same thing?
I'm happy with what it has achieved but ideally I would like to update it. In my controls I create these injected fields often as protected and set them in the constructor for that control.
IBlogService _blogService = null;
IEmailService _emailService = null;
public Templates_BlogTemplate()
{
Inject(ref _blogService);
Inject(ref _emailService);
}
The problem I have with the above is that I have to use "ref" on all objects to actually set the property and I cannot use that on properties directly.
I would prefer to do something along these lines but I don't think it is possible.
IBlogService _blogService = null;
IEmailService _emailService = null;
public Templates_BlogTemplate()
{
Inject(_blogService, _emailService);
}
Has anyone got any ideas of how to neaten the code up or make it work in a cleaner way? I also would want to avoid attributes so it forces the developer to make a decision to inject the variable at a certain point within the control.
All thoughts and feelings are welcome.
Thanks
Support property injection, and inject dependencies to "this".
In my case, I have a base class that calls StructureMap.BuildUp(this), and the user control would have properties like:
public IBlogService _blogService{get;set;}
public IEmailService _emailService{get;set;}
The only line specific to structuremap I have is in the base class. If ninject allows you to do this, then you can call your code handing it the control instance, and let it inject the properties based on its configuration.
You may want to look at IServiceLocator as described by Glenn Block
It's a shared interface that can be used to take advantage of IoC without taking a hard dependency on the container.

Categories

Resources