I came across the following situation.
I have a lot of class files in my project, and, as the project was growing, new functions were being created, but without the correct code review. So, we have some duplicated objects (to access the database, like a controller) being created around the same class, but we don't know if it is better to create only one global object or if we should leave them inside the function, because sometimes the code will not reaches that function, so the object will never be created. If it is global, it will be created every time.
Example:
namespace EventWorks.View
{
public partial class Event : System.Web.UI.Page, ISecurityRules
{
protected void btnNew_Click(object sender, EventArgs e)
{
EventController EventCtrl = new EventController();
//some code
}
protected void btnSave_Click(object sender, EventArgs e)
{
EventController EventCtrl = new EventController();
//some code
}
}
}
My question is, where should I create these objects? It's better to create it globally? Or leave it inside the function and let the garbage collector take care of it? Or make a big analysis and check for every file which option is better?
where should I create these objects?
That really depends on the responsibility of the object, the thread-safety considerations (if there are any), and cost of creating such a global member. There is no "yes make it global" solution to all your problems. You should definitely analyze all your members and decide for each one if it is OK to make them globally available and what effects it would have on your system. For example, keeping a DbContext alive in memory as a single instance would be considered bad practice, since it isn't thread-safe.
If you're only worried about unnecessary objects being created, you can always use the Lazy<T> class which will make sure the value is only lazily initialized on the first access:
private readonly Lazy<EventController> eventController = new
Lazy<EventController>(x => new EventController(), isThreadSafe: true);
If used in multiple functions it can be declared on class level like this (thats not global, but class level):
namespace EventWorks.View
{
public partial class Event : System.Web.UI.Page, ISecurityRules
{
EventController _eventController = new EventController();
protected void btnNew_Click(object sender, EventArgs e)
{
_eventController.DoSomething();
}
protected void btnSave_Click(object sender, EventArgs e)
{
_eventController.DoSomething();
}
}
}
It can be initiliased in constructor also, or it can be injected via dependency injection (Constructor, Interface, setter injection), I guess it all depends what you want.
Often a controller keeps some information on the object status. I.e., whether the object is new or whether it has been loaded from a DB, whether it has pending changes or not and so on.
Therefore it seems more logical to have a controller that has the same life-time as the object (it would be created once per object).
If the controller does not store any object dependent stuff, it could be created once per application lifetime. In this case you could make it a singleton.
public class EventController
{
public static readonly EventController Instance = new EventController();
private EventController()
{
// Make constuctor private, so the class cannot be instantiated elsewhere.
}
// Implement functionality here...
}
call it like this:
EventController.Instance.DoSomething();
Related
I have an interface:
interface ISqlite
{
void insert();
void update();
void delete();
void select();
}
And custom service class:
class SqliteService
{
public SQLiteDatabase driver;
public SqliteService() {
SqliteConnection(new SQLiteDatabase());
}
public void SqliteConnection(SQLiteDatabase driver)
{
this.driver = driver;
}
public void select(ISqlite select) {
select.select();
}
public void insert(ISqlite insert) {
insert.insert();
}
public void delete(ISqlite delete)
{
delete.delete();
}
}
And last class Pacients that realizes ISqlite interface:
class Pacients: ISqlite
{
public List<ClientJson> pacients;
public Pacients() {
this.pacients = new List<ClientJson>();
}
public void add(ClientJson data) {
this.pacients.Add(data);
}
public void insert()
{
throw new NotImplementedException();
}
/* Others methos from interface */
}
I try to use my code like as:
/* Create instance of service class */
SqliteService serviceSqlite = new SqliteService();
/* Create instance of class */
Pacients pacient = new Pacients();
pacient.add(client);
serviceSqlite.insert(pacient);
As you can see above I send object pacient that realizes interface ISqlite to service. It means that will be called method insert from object pacient.
Problem is that I dont understand how to add data in this method using external class: SQLiteDatabase()? How to get access to this.driver in service class from object pacient?
Edit 1
I think I must move instance of connection new SQLiteDatabase() to db inside Pacients class is not it?
Generally speaking, I would favor a solution where the data objects themselves don't know anything about how they're stored, i.e. they have no knowledge of the class that communicates with the database. Many ORMs do just that.
Of course it might not be easy depending on the specifics of your situation... Try to examine what your methods on each object actually need; generally speaking they need the values of properties, and what column each property corresponds to, right? So any external class can do this if it knows these bits of information. You can specify the name of the column with a custom attribute on each property (and if the attribute isn't there, the column must have the same name as the property).
And again, this is the most basic thing that ORMs (Object Relational Mappers) do, and in addition they also manage more complicated things like relationships between objects/tables. I'm sure there are many ORMs that work with SqlLite. If you're OK with taking the time to learn the specifics of an ORM, that's what I would recommend using - although they're not silver bullets and will never satisfy all possible requirements, they are in my opinion perfect for automating the most common day to day things.
More to the point of the question, you can of course make it work like that if you pass the SQLiteDatabase object to the methods, or keep it in a private field and require it in the constructor or otherwise make sure that it's available when you need it; there's no other simple solution I can think of. And like you pointed out, it implies a certain degree of coupling.
You can change the signature of interface's methods to pass an SQLiteDatabase object.
interface ISqlite
{
void insert(SQLiteDatabase driver);
void update(SQLiteDatabase driver);
void delete(SQLiteDatabase driver);
void select(SQLiteDatabase driver);
}
Example call from the service:
public void insert(ISqlite insert)
{
insert.insert(driver);
}
I think you can figure out the rest by yourself.
I always get tied up with small things like this... I need to access an objects properties created in class 'Login' from my welcome page class 'Default'. When I try to reference the class so that I may access the object, VS 2010 doesn't list it as available like it normally would, and forcing the request just returns an error.
My Login Class is defined like so:
public abstract class Login : System.Web.UI.UserControl
{
...
private void Login_click(object sender, EventArgs e)
{
MyObject myObject = new MyObject();
myObject.property1 = "something";
}
}
And then i wish to access myObject from my default class, like this:
public class Default : System.Web.UI.Page
{
...
private void Page_load(object sender, System.EventArgs e)
{
string someLocalVar = Login.myObject.property1;
}
}
Where property1 is a property set in the Login class. This does not work, however, and VS doesn't even recognize the Login class; instead it treats it as a reserved word of some sort. These two files are in the same project, so that shouldn't be an issue in the using section. I've accessed variables in this manner between other classes before, just not this time for some reason.
Thanks!
2 things:
Your class is abstract
Your property is probably not static
You don't actually have a property, it's a local variable
You can't instantiate an instance of an abstract class. The point of an abstract class is to create a class with some shared code that other, similar child classes can inherit. Is there a reason your class is abstract?
If your property is not static you have to create an instance of your class in order to access the property. (Which, as I describe above, you can't because it's abstract). If you make your property static, you could then do Login.MyObject without creating an instance.
In the code you supplied, your variable is local to the Login_click method, which means even if you created an instance of your class you wouldn't be able to access it.
I suggest you pick up a C# book and read up on the fundamentals.
There's a number of issues here. First, you're accessing myObject like it's a member of Login, which it isn't. It's a local variable to your Login_click method. Second, you never create an instance of Login in your Default class, so unless it's a static class or you actually create an instance of it, you're not going to be able to access any members of it.
Here's something more like what you want (I think). I've left out your class inheritance for now.
public class Login
{
MyObject object;
public Login() {
object = new MyObject();
object.property1 = "something";
}
}
public class Default {
private void Login_click(object sender, EventArgs e)
{
Login _login = new Login();
string someLocalVar = _login.object.property1;
}
}
Like others have said, you need to more carefully plan this out and strengthen your programming skills before attempting this. This is basic stuff so it shouldn't take an exorbitant amount of time -- don't worry though, we all started here.
You can put your object into a Session variable, and then Cast it back.
//in Login.aspx
MyObject myObject = new MyObject();
myObject.property1 = "something";
Session["UserObject"] = myObject;
//in default.aspx
MyObject obj = (MyObject)Session["UserObject"]
string variable = obj.property1;
In my SharePoint 2010 c# / asp.net site, I have a class defined like
namespace PDF_Library.VisualWebPart1
{
public partial class PDF_Library : Usercontrol
{
public static PDF_Library current;
protected void Page_Load(object sender, EventArgs e)
{
current = (PDF_Library)this;
}
}
}
public static class Page_State
{
public static Page is_display()
{
return PDF_Library.current.Page; // didn't work...
}
}
It doesn't have a constructor.
How can I get the reference to the current instance of this class?
I tried something like this in the top
public static PDF_Library current;
Then in a function it had
current = (PDF_Library)this;
But that didn't work...
You need to understand that it does not work this way. Your question is tagged with asp.net - multi-user, multi-threaded environment where multiple instances of PDF_Library user control will be created all the time. It is absolutely uncertain which one of them will be hanging off PDF_Library.current. You need to rethink your design.
More on this: Page instance is disposed of when the request processing is finished. Normally this instance with all its controls and things such as Response, Request, Context etc will be set for garbage collection. Because you keep a reference to a UserControl instance in a static field, all these objects (including Page) will be kept in memory until this current reference is replaced with something else.
It is the fact that you used static in the function that was assinging current that this did not work. static is a method that is not tied to any instance of the class, therefor you can not use this.
Your only options are either make the method non-static or pass in a instance of the class as a parameter to the static function.
From what I can tell you are trying to create a "Singleton Pattern". See the link to the previous MSDN article for examples on how to create a singleton class.
This looks like it will have an instance. If the class is marked as static (which it doesn't appear to be) then you can just reference it by name "PDF_Library". Other wise, use ILSpy or reflector to look at the end result. I bet it has a constructor; just because you don't see one, doesn't mean it isn't there. Override the default ctor and set your instance there.
namespace PDF_Library.VisualWebPart1
{
public partial class PDF_Library : Usercontrol
{
public static PDF_Library Current;
public PDF_Library() : base() {
Current = this;
}
}
}
The problem you might be having with your Page_Load code is that it's being called too late in the lifecycle and that's why your reference call isn't working.
I've a problem with my C# Code. At the moment I try to program a Windows Forms Application with more than one Window.
Now my problem:
At the first window I've a combobox with some values. When I click on a button, the second window opens and there it should be possible to add a value to this combobox on the first form.
The problem is that in the first window I´ve a LinkedList where my values are in.
Like this:
public LinkedList<String> sample = new LinkedList<String>();
hase.AddFirst("test");
combobox.Items.AddRange(sample.ToArray());
Now, in the second window the LinkedList isn't available, even if I make it public.
What is the best way to solve this problem?
Hope you understand my problem...
Harald
Without knowing exactly how to are trying to access the LinkedList, it's hard to say why it isn't working for you.
Let's go over what you have. You have a LinkedList, which is an instance variable on a form. Since this LinkedList is an instance variable, it is associated with the instance of the form.
This example below, will not work because it tries to access it statically:
public class MyForm : Form
{
public LinkedList<string> _list = new LinkedList<string>();
}
public class MySecondForm : Form
{
public void Window_Loaded(object sender, EventArgs e)
{
MyForm._list.AddFirst("This doesn't work");
//WRONG! list is an instance variable we are trying to access statically.
}
}
So, we can see this does not work. We have a few options to get this working. First off, one very bad solution would be to actually make list static. Don't use this option. It's opens the door for concurrency problems, possibly leaking strong references, etc. Generally, using statics (like a singleton) I would discourage for passing data around for these reasons. The Singleton Pattern has a time and a place, but I don't think this is it since it can so easily be avoided.
OK, since we got the bad solution out of the way, let's look at a few possible good ones.
Set the list on MySecondForm. You have a few options for this. The constructor, a property, or a method. For example:
public class MyForm : Form
{
private LinkedList<string> _list = new LinkedList<string>();
public void Button1_Click(object sender, EventArgs e)
{
var secondForm = new MySecondForm();
secondForm.SetList(_list);
secondForm.ShowDialog();
MessageBox.Show(_list.First.Value);
}
}
public class MySecondForm : Form
{
private LinkedList<string> _list;
public void Window_Loaded(object sender, EventArgs e)
{
this._list.AddFirst("This will work");
}
public void SetList(LinkedList<string> list)
{
_list = list;
}
}
This is one possible solution. The constructor is another possible solution as Billy suggested.
Because LinkedList is a reference type, any changes you make to it on the instance of MySecondForm will be reflected on the linked list of MyForm.
You can always pass it to the second window. As vcsjones points out below, you should only need to add the ref keyword if you are re-assigning the list. You will need a constructor that takes a linked list as a variable.
SecondWindow secondWindow = new SecondWindow(sample);
Another way would be create a class using the singleton pattern and you can place the linked list in there. You would then have access to it from both windows if it was in a common location.
In most examples of dependency injection, I see simple objects being injected, such as in the example below SecurityManager gets injected into MainApplication.
However, it would seem natural to inject delegates as well, as in the example below LogHandler gets injected into MainApplication.
Are delegates generally not used in dependency injection? What would be reasons for and against their use?
using System;
using System.Windows;
using System.Windows.Controls;
namespace TestSimpleDelegate82343
{
public partial class Window1 : Window
{
public delegate void LogHandler(string message);
public Window1()
{
InitializeComponent();
}
private void Button_Gui_Lax_Click(object sender, RoutedEventArgs e)
{
MainApplication app = new MainApplication(new LogHandler(GuiLogHandler), new LaxSecurityManager());
}
private void Button_Console_Lax_Click(object sender, RoutedEventArgs e)
{
MainApplication app = new MainApplication(new LogHandler(ConsoleLogHandler), new LaxSecurityManager());
}
private void Button_Gui_Tough_Click(object sender, RoutedEventArgs e)
{
MainApplication app = new MainApplication(new LogHandler(GuiLogHandler), new ToughSecurityManager());
}
private void Button_Console_Tough_Click(object sender, RoutedEventArgs e)
{
MainApplication app = new MainApplication(new LogHandler(ConsoleLogHandler), new ToughSecurityManager());
}
public void GuiLogHandler(string message)
{
TextBlock tb = new TextBlock();
tb.Text = "logging: " + message;
TheContent.Children.Add(tb);
}
public void ConsoleLogHandler(string message)
{
Console.WriteLine("logging: " + message);
}
}
public interface ISecurityManager
{
bool UserIsEntitled();
}
public class LaxSecurityManager : ISecurityManager
{
public bool UserIsEntitled()
{
return true;
}
}
public class ToughSecurityManager : ISecurityManager
{
public bool UserIsEntitled()
{
return false;
}
}
public class MainApplication
{
public MainApplication(Window1.LogHandler logHandler, ISecurityManager securityManager)
{
logHandler("test1");
logHandler("test2");
logHandler("test3");
if (securityManager.UserIsEntitled())
{
logHandler("secret");
}
}
}
}
I occasionally use delegates as Anonymous Interfaces - also for DI.
One issue with this approach, however, is that it becomes a little bit more difficult to unit test that the correct Dependency was injected and used in a class, because a delegate instance isn't a type, and sometimes you'd simply just want to verify that a class uses the correct type of Strategy/Dependency.
Going back to object oriented principles, one of the key features of an object is that it has behaviour and state. I could envision a scenario where a log handler might need to maintain some sort of state (logfilename, db connection, etc.), but there might also be an argument for a log handler not needing to concern itself with state.
If your dependency needs to manage state of its own, use a proper object (rather, an interface).
If your dependency has only behaviour and not state, then a delegate might be suitable, although some people might be more comfortable using a proper object (interface) anyway, as it might be easier to add state management to it later on if needed.
A benefit of delegates is that they're CRAZY simple to mock with lambda expressions :) (even though interfaces are pretty easy to mock, too)
Now of course any delegate can still just be some normal method on some normal object, and that method can totally have behaviour that affects the state of the object, and there are certainly valid reasons to do that, but you're approaching the point where it might make more sense just to take a dependency on the whole object, instead of just one of its methods.
Further down this path, injecting delegates can also be a way to apply Interface Segregation Principle, so you can make sure your system isn't dependent on things it doesn't use.
One further note about delegates...
There's almost never a good reason to define your own delegate type. Most of the use cases fit into the Func<> and Action<> C# types (and events, but that's another issue).
In your case, your MainApplication constructor should not take a Window1.LogHandler as a parameter, but instead just an Action<string>. Then you'd just call it with:
MainApplication app = new MainApplication(ConsoleLogHandler, new ToughSecurityManager());
or similar, since the ConsoleLogHandler method already fits the Action<string> signature.
And in your test, you'd just instanciate it with:
MainApplication app = new MainApplication(x => { /*Do nothing*/ }, new MySecurityManagerStub());
or even better:
int timesCalled;
MainApplication app = new MainApplication(x => { timesCalled++ }, new MySecurityManagerStub());
Then you can verify that MainApplication called the method exactly as many times as you intended.
I know that MEF for example allows injecting delegates. However you can also make an ILog interface that has a Log method with the same signature as your delegate. I think it'll be much clearer to understand that the intend was to inject an implementation of an object capable of logging rather than a single log function.