Reputation: 23
I have a List in Class 1. I have a helper class (Class 2) which is instantiated inside Class 1. Class 2 should then do some work and update the List in Class 1.
I tried passing Class 1 into the Constructor of Class 2, but this only modifies the version within Class 2.
public class Server // Class 1
{
private string m_serverName;
private string m_loginUsername;
private string m_loginPassword;
private ServerConnectionTools m_connectionTools;
public List<Service> Services { get; private set; }
public Server(string serverName, string loginUsername, string loginPassword)
{
this.ServerName = serverName;
this.LoginUsername = loginUsername;
this.LoginPassword = loginPassword;
// Login to server and retrieve list of services
ConnectionTools = new ServerConnectionTools(this);
}
}
public class ServerConnectionTools // Class 2
{
private Server m_server;
private ManagementScope m_scope;
public ServerConnectionTools(Server server)
{
this.Server = server;
this.Scope = InitiateScope();
try
{
// Once this is finished updating, I need to update the Service List in Class 1.
this.UpdateServicesList();
}
catch (System.Runtime.InteropServices.COMException)
{
// Server is unavailable
Console.WriteLine("Unable to reach server {0}", server.ServerName);
}
}
public ManagementScope InitiateScope()
{
ManagementScope scope;
// If server is Remote server, log in with Credentials
// otherwise no need to connect.
if (System.Environment.MachineName.ToLower() != this.Server.ServerName.ToLower())
{
// Is a remote server, need credentials
ConnectionOptions options = new ConnectionOptions();
options.Username = this.Server.LoginUsername;
options.Password = this.Server.LoginPassword;
scope = new ManagementScope("\\\\" + this.Server.ServerName + "\\root\\cimv2", options);
}
else
{
// Local machine, no need for credentials
scope = new ManagementScope("\\\\" + this.Server.ServerName + "\\root\\cimv2");
}
return scope;
}
public void UpdateServicesList()
{
// Connect our scope to the actual WMI scope
this.Scope.Connect();
List<StringBuilder> servicesList = new List<StringBuilder>();
// Query system for Services
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Service WHERE Caption LIKE 'xxx%'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(this.Scope, query);
ManagementObjectCollection services = searcher.Get();
if (services.Count > 0)
{
foreach (ManagementObject queryObj in services)
{
StringBuilder s = new StringBuilder();
s.Append(queryObj["Caption"].ToString());
s.Append(",");
s.Append(queryObj["State"].ToString());
s.Append(",");
s.Append(queryObj["ProcessId"].ToString());
s.Append(";");
servicesList.Add(s);
}
}
}
Edit: Added code, thought I was doing right by keeping it simple! So when I run this.UpdateServicesList(); in the constructor of the ServerConnectionTools class, I need to update the List in the Server class.
Edit2: While typing this I had a brainwave... Return a list of services from the update function and call the update function from the first class. Think this is a better approach?
What is the best approach to doing this?
Apologies for what is probably a simple question...
Cheers Dave
Upvotes: 0
Views: 572
Reputation: 1690
In your situation you don't need whole service class in serviceConnectionTools. here is my suggestion to you Step 1 add an interface
interface caller
{
void setList(List<StringBuilder> par_list);
}
Step 2 implement the interface public class Server : caller {
private string m_serverName;
private string m_loginUsername;
private string m_loginPassword;
private ServerConnectionTools m_connectionTools;
public List<Service> Services { get; private set; }
public Server(string serverName, string loginUsername, string loginPassword)
{
this.ServerName = serverName;
this.LoginUsername = loginUsername;
this.LoginPassword = loginPassword;
// Login to server and retrieve list of services
ConnectionTools = new ServerConnectionTools(this);
}
public void setList(List<StringBuilder> par_list)
{
//do whatever you need to here.
}
}
step 3
public class ServerConnectionTools // Class 2
{
private caller m_serverCB;
private ManagementScope m_scope;
public ServerConnectionTools(caller par_serverCB)
{
m_serverCB = par_serverCB;
this.Scope = InitiateScope();
try
{
this.UpdateServicesList();
}
catch (System.Runtime.InteropServices.COMException)
{
// Server is unavailable
Console.WriteLine("Unable to reach server {0}", server.ServerName);
}
}
/// in your Updateservicelist function
public void UpdateServicesList()
{
// Connect our scope to the actual WMI scope
this.Scope.Connect();
List<StringBuilder> servicesList = new List<StringBuilder>();
// Query system for Services
ObjectQuery query = new ObjectQuery("SELECT * FROM Win32_Service WHERE Caption LIKE 'xxx%'");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(this.Scope, query);
ManagementObjectCollection services = searcher.Get();
if (services.Count > 0)
{
foreach (ManagementObject queryObj in services)
{
StringBuilder s = new StringBuilder();
s.Append(queryObj["Caption"].ToString());
s.Append(",");
s.Append(queryObj["State"].ToString());
s.Append(",");
s.Append(queryObj["ProcessId"].ToString());
s.Append(";");
servicesList.Add(s);
}
}
m_serverCB.setList(servicesList);//add this to call method.
}
Now you don't have to send all server object to class2. You can use serverConnectionTools for other classed you may need in the future instead of just using only one class.You have better oop implementation now I hope.
Upvotes: 0
Reputation: 1195
Use delegates.
Like this:
// Delegate Specification
public class MyClass
{
// Declare a delegate that takes a single string parameter
// and has no return type.
public delegate void LogHandler(string message);
// The use of the delegate is just like calling a function directly,
// though we need to add a check to see if the delegate is null
// (that is, not pointing to a function) before calling the function.
public void Process(LogHandler logHandler)
{
if (logHandler != null)
{
logHandler("Process() begin");
}
if (logHandler != null)
{
logHandler ("Process() end");
}
}
}
// Test Application to use the defined Delegate
public class TestApplication
{
// Static Function: To which is used in the Delegate. To call the Process()
// function, we need to declare a logging function: Logger() that matches
// the signature of the delegate.
static void Logger(string s)
{
Console.WriteLine(s);
}
static void Main(string[] args)
{
MyClass myClass = new MyClass();
// Crate an instance of the delegate, pointing to the logging function.
// This delegate will then be passed to the Process() function.
MyClass.LogHandler myLogger = new MyClass.LogHandler(Logger);
myClass.Process(myLogger);
}
}
Upvotes: 0
Reputation: 1056
Edit: Removed code snippet after your edits.
Yes, return a list of services. That's much better than sending in the parent class to the helper class.
You don't appear to be using the server that you send into the helper class. So you can just fetch the services from the update function. I would rename the update function to FetchServices or something instead of update.
public Server(string serverName, string loginUsername, string loginPassword)
{
this.ServerName = serverName;
this.LoginUsername = loginUsername;
this.LoginPassword = loginPassword;
// Login to server and retrieve list of services
ConnectionTools = new ServerConnectionTools(this);
this.Services = ConnectionTools.FetchServiceTools();
}
Upvotes: 1