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/
Related
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.
In one module, I have a binding set up for an object. There are two other modules: a testing module and a web module. The web module wants that binding to be in request scope, and the testing module wants that binding to be in singleton scope. Right now, we are just duplicating the entire binding and adding the appropriate scope. Is there a better way to do this? I am looking for a way that I can make the binding itself (it's a ToMethod binding) in the one module, and then just have the testing and web modules just change the scope on that binding.
This scenario is not specifically supported by ninject, and most likely also not by any other IoC.
Especially Scoping, but there also may be other things like context parameters and the way one resolves certain types and configuration, is something which is often dependent on the application / composition root.
But of course you can make use of the "normal" programming principles to lessen the burden, if you so wish. But i would not really recommend it because while you may make the scope easily configurable it will make other things more complicated and harder to maintain. For example:
public class ConfigurableScopeBindingModule : NinjectModule
{
private readonly Action<IBindingInSyntax<object>> scopeConfigurator;
public ConfigurableScopeBindingModule(Action<IBindingInSyntax<object>> scopeConfigurator)
{
this.scopeConfigurator = scopeConfigurator;
}
public override void Load()
{
this.BindAndApplyScoping(x => x.Bind(typeof(string)).ToSelf());
}
private void BindAndApplyScoping(Func<IBindingRoot, IBindingInSyntax<object>> binding)
{
this.scopeConfigurator(binding(this));
}
}
and use like:
IKernel.Load(new ConfigurableScopeBindingModule(x => x.InSingletonScope()));
Using Ninject, simply use the Bind<T>().ToSelf() - and then add whatever scope you want (Bind<T>().ToSelf().InRequestScope(), for example).
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.
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.
In my asp.net web app. I have three classes (inside app_code folder) under namespace WPP which are as follows:
1. wpp_Common
2. wpp_SQL
3. wpp_Admin
All these classes contains different functions which I am using in my application to accomplish different tasks. Such as, wpp_common contains a function which make my URL's SEO'd, and wpp_SQL have some functions which I am using to get details from database.
Now, I am using these classes on different web pages web pages and in web controls. To use these classes I am creating instances of all three classes on the page where I am using them.
protected WPP.wpp_Common ObjCommon = new WPP.wpp_Common();
protected WPP.wpp_SQL ObjSQL = new WPP.wpp_SQL();
protected WPP.wpp_Admin ObjAdmin = new WPP.wpp_Admin();
So, I want to know, is this a better and only way to access my classes by making seprate instances at every page, is this method have any performance constraints.
Or is there a better and logical way to access my classes from ASP.net web pages and web controls.
Thanks.
If these classes don't encapsulate anything mutable, it may be worth making the key methods utilized static. Then, you don't even need an instance of the class. This seems to make sense for your SEO class. The SQL class you may want a shared instance as it may contain a reference to some SQL connection/class, but this could also be a parameter in a static method.
What you're doing seems okay to me, though.
Really the answer boils down to the complexity of the class. If your classes are lightweight and have low initialization overhead, then you are probably OK with instatiating objects every time. (Heck, even the ASP.NET runtime creates a new instance of your page object every time in classic ASP.NET - not sure about MVC).
But if your object has non-trivial initialization time (intensive processing in constructor or upon first method call), then you'll probably want to look at two options:
One) Storing the object in the session - be careful here as your object may behave differently depending on the backend session store (memory, sql, etc).
MyHeavyObj obj = (MyHeaveyObj) Session["cachedObj"];
if (obj == null)
{
obj = new MyHeavyObj();
obj.Init();
Session["cachedObj"] = obj;
}
obj.DoSomething();
Two) Writing your own Windows Service that serves up your objects via remoting and takes care of initiatlization internally. The drawback here is you need to make sure your service scales as your traffic grows.
MyHeavyObj obj = GetHeavyObjViaRemoting();
obj.DoSomething();