This is a kind of a newbie question. I haven't done C# programming in a while especially with creating with custom classes. I want to share some data between my forms, I was thinking of creating a class,
public class User
{
public string id;
public string name;
public User()
{
}
public User(string id, string name)
{
this.id = id;
this.name = name;
}
}
Does the class have to be in a separate file (User.cs)?
If I had the following code:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
User user1 = new User("abc","cde");
}
}
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
}
How should I create the class in Form1 and how should I access it in Form2?
Typically, you separate classes out into separate files, so I would suggest making a User.cs file that contains the User class.
How you are instantiating the class in Form1 is fine, but to get the instance of the class to Form2 you need to pass it to the constructor of Form2, like this:
Form2 theForm2 = new Form2(user1);
Note: To accomplish the code above requires modifying the constructor of Form2, or in this case creating a non-default constructor, and creating a member variable to hold the User class instance, like this:
public partial class Form2 : Form
{
private User _user;
public User TheUser
{
get
{
return _user;
}
}
public Form2()
{
InitializeComponent();
}
public Form2(User theUser)
{
_user = theUser;
}
}
Now you can use the User class in Form2 by simply referencing the property TheUser.
How you distribute the classes ove files its all up to you. In this example I made you could have UserHandler.cs, User.cs, Form1.cs & Form2.cs. Hope it helps.
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public static class UserHandler
{
private static List<User> Users = new List<User>();
public static void AddNewUser(User user)
{
Users.Add(user);
}
public static void RemoveUser(User user)
{
Users.Remove(user);
}
public static User GetUserById(int id)
{
if(Users.Exists(x => x.userId == id))
{
return Users.Find(user => user.userId == id);
}
return null;
}
}
public class User
{
public int userId { get; set; }
public string userName { get; set; }
public User(int id, string name)
{
this.userId = id;
this.userName = name;
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var _user = new User(1,"user2252502");
UserHandler.AddNewUser(_user);
MessageBox.Show(UserHandler.GetUserById(1).userName);
Form2 form2 = new Form2();
}
}
public partial class Form2 : Form
{
public Form2()
{
MessageBox.Show(UserHandler.GetUserById(1).userName);
}
}
}
There are multiple ways of doing this. one way can be that you pass the class in constructor of Form2. like below.
public partial class Form1 : Form
{
User user1 = new User("abc","cde");
public Form1()
{
InitializeComponent();
new Form2(user1);
}
}
public partial class Form2 : Form
{
User user1;
public Form2(User u)
{
InitializeComponent();
user1 = u;
}
}
Other ways of doing this can be to expose a public property in form1 that returns User. and you access that property in Form2.
They can be in the same file. If you want to access data from Form1 in Form2, add Form1 as a parameter to the constructor of Form2. Or add it as a property in Form2 and allow it to be "set".
How should I create the class in Form1 and How should I access it in Form 2?
This depends on its use. Since your desire is to share it between forms, I am assuming you would like its scope to be class wide. Define it as a class property. Preferably above your constructor for Form1.
Does the class have to be in a separate file, User.cs If I had the following code
It does not have to be, but best practice is that it is.
How do I share it with Form2?
A. Make it a parameter of the constructor of Form2:
public partial class Form2 : Form
{
public User MyUser { get; set; }
public Form2(User user)
{
InitializeComponent();
MyUser = user;
}
}
B. Make it a public property of Form2 and set it from Form1
var frm2 = new Form2();
frm2.User = user;
I'm speaking purely from a "I think I've been down the same road you're going down" point of view.
It might be time to break down your application into some patterns. A User class is usually a special kind of entity within an application. In typical cases, it can define the attributes of a user, or it can be used to define the Identity and Claims for a particular user, or all of the above.
It would be good to make a service or utility class for your user. If any given Form, or class for that matter, in your application needs to have information about a User, your service is there to answer the call. This service could provide a CurrentUser property which would inform other classes that the currently logged in user is (null | Bob | xyz...) It can perform validation, access background utilities to cache attributes about the user. but I digress. While writing my answer, #Iker Ruiz Amauda has given a practical example of how might implement this service.
As to how to make this available across your application: it depends on the magnitude of your project. I've like Dependency Injection as mentioned by Karl Anderson. To go along with Dependency Injection would be Inversion of control (IoC). My current flavor of IoC is MEF (http://mef.codeplex.com/documentation). By defining an IUserService that is implemented by UserService, you can "Inject" this service into any form that relies on the userservice. In my current project this is achieved practically using attributes to export and import items.
For more information on Inversion of Control (I think Dependency Injection is pretty straight forward but Google is your friend on that one,) see This answer on stack overflow:
https://stackoverflow.com/a/3140/93964
or this was a decent blog entry I found while google the subject:
http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/
Related
I have question. I use to use Send to pass the viewmodel to show other page as shown below:
public class UsersViewModel : IUsersViewModel
{
void ShowCars()
{
MessagingCenter.Send<IUsersViewModel>(this, "ShowCarsViewPage");
}
}
As you see above, i use this. Now i have situation that i need to pass diffrent viewmoodel inside UsersViewModel. I want to add ShowBuildings inside UsersViewModel. The problem is as it's diffrent viewmodel to be passed i cannot use this which leds me to use new keyword and pass all dependencies. How can i overcome that?
void ShowBuildings()
{
MessagingCenter.Send<IBuildingsViewModel>(new Buildings(new DataStorage()), "ShowBuildingsViewPage");
}
My first thought is to pass that view model i need to use into UsersViewModel's ctor but not sure if this is right way like to insert another view model into other view model?:
public class UsersViewModel : IUsersViewModel
{
private readonly IBuildingsViewModel _buildingviewmodel;
UsersViewMode(IBuildingsViewModel buildingviewmodel)
{
_buildingviewmodel = buildingviewmodel;
}
//So then:
void ShowBuildings()
{
MessagingCenter.Send<IBuildingsViewModel>(_buildingviewmodel, "ShowBuildingsViewPage");
}
}
Check xamarin publisher documentation. The third parameter is the payload data that is being sent.
MessagingCenter.Send<MainPage, string>(this, "Hi", "John");
Tip: Try to bundle multiple ViewModels with an interface and pass that. In this way you will not be tied to specific ViewModels interfaces.
interface IBuildingCollection : IEnumerable<Building>
{
}
class ViewModel1 : IBuildingsViewModel, IBuildingCollection
{
}
class ViewModel2 : IBuildingsViewModel, IBuildingCollection
{
}
class UsersViewModel : IUsersViewModel
{
void ShowBuildings(IBuildingCollection collection)
{
MessagingCenter.Send<IUsersViewModel, IBuildingCollection>(this, "ShowBuildingsViewPage", collection);
}
}
class ReceiverViewModel : IReceiverViewModel
{
public ReceiverViewModel()
{
MessagingCenter.Subscribe<IUsersViewModel, IBuildingCollection>(this, "ShowBuildingsViewPage", myDelegate);
}
public void myDelegate(IBuildingCollection buildings)
{
// Do something with buildings
}
}
I'm trying to achieve maybe something that might be impossible.
We have a big MVC 5 application. I created a small MVC project to simulate and explain what I want to apply into that big MVC project.
I have a controller that has unique Id. In this sample project the unique Id is regenerated for each request. In the MVC project, it is a bit more complex and different. However it's not relevant in the scope of this example.
public class FooController : Controller
{
public string UniqueId = Guid.NewGuid().ToString("N");
public ActionResult Index()
{
var worker = new WorkerA();
worker.DoWork();
return View();
}
}
The FooController creates WorkerA which creates WorkerB which creates WorkerC and so on. The workers are not the same. They don't have the same interface/implementation. To make the example simple I made them look similar.
Here's the Workers:
public class WorkerA
{
public string UniqueId = string.Empty;
public void DoWork()
{
var worker = new WorkerB();
worker.DoWork();
//...
//...
}
}
public class WorkerB
{
public string UniqueId = string.Empty;
public void DoWork()
{
var worker = new WorkerC();
worker.DoWork();
}
}
I want to have inject the property UniqueId into the worker without having to passing it as a parameter.
I want to avoid having to do this:
public WorkerA(string uniqueId)
{
UniqueId = uniqueId;
}
But I need to do the same for all the other workers.
EDIT
Is there a way to acheive that with ninject?
You can achieve what you want using Microsoft.Practices.Unity in the following manner:
public class WorkerA
{
[Dependency]
public string UniqueId { get; set; }
}
public class WorkerB
{
[Dependency]
public string UniqueId { get; set; }
}
And after that :
var container = new UnityContainer();
container.RegisterType<WorkerA>(new InjectionProperty(nameof(WorkerA.UniqueId),"WorkerAValue"));
container.RegisterType<WorkerA>(new InjectionProperty(nameof(WorkerB.UniqueId), "WorkerBValue"));
Later, you can request the instances from the container with the desired properties configured:
var workerA = container.Resolve<WorkerA>();
var workerB = container.Resolve<WorkerB>();
You can do something like:
worker.GetType().GetField("prop")?.SetValue(worker, "guid");
You could create a singleton class to manage the GUID and deliver it to the child classes that way. This way you can still do it in a constructor but not have to pass it as a parameter
public class GUIDManager
{
private static GUIDManager _instance;
private Guid _activeGuid;
public Guid ActiveGuid {
get { return _activeGuid; }
set { _activeGuid = value; }
}
private GUIDManager()
{
if (_activeGuid == null)
_activeGuid = new Guid();
}
public static GUIDManager GetInstance()
{
if(_instance == null)
{
_instance = new GUIDManager();
}
return _instance;
}
}
public class WorkerB
{
public string UniqueId = string.Empty;
public WorkerB()
{
var manager = GUIDManager.GetInstance();
UniqueId = manager.ActiveGuid.ToString();
}
public void DoWork()
{
var worker = new WorkerC();
worker.DoWork();
}
}
From your question i'm not entirely clear about all the workers in the same request getting the same ID or not. If they all should get the same ID then it's simple:
Wrap the ID in a class and use InRequestScope():
public class BrowserTabId
{
public string browserTabId;
public BrowserTabId(string tabId)
{
if(string.IsNullOrEmpty(tabId))
{
throw new NullArgumentException();
}
this.browserTabId = tabId;
}
public string Id { get { return this.browserTabId; } }
}
Bind<BrowserTabId>()
.ToMethod(ctx =>
new BrowserTabId(HttpContext.Items["BrowserTabId"] as string)))
.InRequestScope();
For testability reasons you can also slap on an interface IUniqueRequestId and create the binding for that.
This will result in all workers / objects created during the same request receiveing the same BrowserTabId. If you don't want to use c-tor injection you can use property injection instead. If you don't want to inject the value all the type, then use a When(..) condition to specify when to inject and when not to. Combine this with the null-object pattern to keep ninject from complaining that it can't inject a requested type.
Property Injection
Adapt a worker as follows:
public class WorkerA
{
[Inject]
public BrowserTabId BrowserTabId { get; set; }
....
}
Note, however, for this to work, like normal constructor injection, it is necessary that either the WorkerA is instanciated by ninject or that Ninject is informed about its existence by Ninject.Inject(workerAInstance)
Scoping
Since you mention that the lifetime of the ID in your actual application is somewhat more complicated, I guess you will have to use something different than InRequestScope - maybe roll your own scope (by using InScope(...)). Or Maybe, InCallScope() is as viable alternative. However, without knowing what exactly it is what you need, it's a bit difficult to advise you properly.
I am currently making a WPF application and am now ready to add a mongo database, however I can't seem to find the best process to do this with. right now I am doing it like so:
MongoManagment.cs:
namespace MoneyManagment
{
class MongoManagment
{
public void Connect()
{
String connectionString = "mongodb://localhost";
MongoClient client = new MongoClient(connectionString);
MongoServer server = client.GetServer();
MongoDatabase database = server.GetDatabase("MoneyManagment"); //Connect to the database
MongoCollection<Users> _users = database.GetCollection<Users>("user"); // "user" is the collection name, "Users" is the domain class
}
}
public class Users
{
public ObjectId _id { get; set; }
public string username { get; set; }
}
}
then I try to access the data from the domain class in MainWindow.xaml.cs:
namespace MoneyManagment
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
foreach (Users user in _users.FindAll())
{
//do something with users data here
}
}
}
And I get an error here that VS can not access _users, which to an extent makes sense, the problem is though, I have tried a plethora of different ways to make that accessible and it's just not working which leads me to believe that there is a better way to go about this. Any ideas?
First, you need the variable that you want to access to be publicly visible.
public class MongoManagment
{
public MongoCollection<Users> MongoUsers {get; set;}
public void Connect()
{
....
this.MongoUsers = database.GetCollection<Users>("user");
}
then, you need to reference the object in the external class:
public MainWindow()
{
....
MongoManagement mm = new MongoManagement();
mm.Connect();
foreach (Users user in mm.MongoUsers.FindAll())
{
//do something with users data here
}
note this is a very simplistic example, and you may not want a copy of MongoManagment for every window, etc. You will still want to spend a bit of time exploring the concepts of variable lifecycles, scope....
I linq to sql I could make a partial view and do something like this
public partial class User
{
partial void OnNameChanged()
{
UserName = StringFormatter.ToTitleCase(UserName.Trim());
}
partial void OnEmailChanged()
{
Email = Email.ToLower().Trim();
}
}
can I do something like this in nhibernate. Also if you can. Can you do something like that OnQuery or OnSave?
The best way to do that with NHibernate would be to use the property accessors directly:
public class User
{
...
private string userName;
public virtual string UserName
{
get{return StringFormatter.ToTitleCase(userName.Trim());}
set{userName = StringFormatter.ToTitleCase(value.Trim());}
}
private string email
public virtual string Email
{
get{return email.Trim().ToLower();}
set{email= value.Trim().ToLower();}
}
...
}
Since NHibernate doesn't generate the DAO, but instead just uses your existing domain object, you have complete control over get/set logic. No need for a partial (though you could set it up that way to, if you really wanted).
I've got a business logic layer class containing access methods for each table in a database. As there are quite a few tables now I'd like to restructure it to group the methods by entity (for easier access when coding). So, from this:
BLL.Database MyDB = new BLL.Database();
BLL.Entity.User MyUser = Database.UserGetById(42);
to this:
BLL.Database MyDB = new BLL.Database();
BLL.Entity.User MyUser = Database.User.GetById(42);
I'd like the class to remain non-static if possible, with all the classes 'partial' too (to allow me to add additional methods to the main generated class). What are my options for achieving this? Here's the current layout:
namespace BLL
{
public partial class Database
{
// private members..
// constructor
#region User
public IQueryable<BLL.Entity.User> UserGetAll()
{
// ...
}
public BLL.Entity.User UserGetById(int UserId)
{
// ...
}
public void UserSave(ref BLL.Entity.User user)
{
// ...
}
public void UserDelete(int userId)
{
// ...
}
#endregion
// More sets of methods for other entities in database here..
}
}
Is this feasible?
namespace BLL
{
public partial class Database
{
private _User;
public User
{
if (_User == null)
{
_User = new User();
}
return _User;
}
// Other data access classes here..
}
public partial class User
{
public IQueryable<BLL.Entity.User> GetAll()
{
// ...
}
// GetById, Save & Delete methods here..
}
}
Thanks.
Aside from the use of partial, your layout looks good. I don't think partial is going to do the trick for you as far as making the classes extensible, as partial classes must all reside in the same assembly.
A better solution would likely be creating extension methods.
Yes, that is feasible. In fact I implemented something a lot like that.
Of course, after doing so I heard about Linq to SQL and we started using that instead... so you might want to check that out as another option.