dc799
dc799

Reputation: 23

Update Parent object from within Child

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

Answers (3)

Burak Karasoy
Burak Karasoy

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

Igor Quirino
Igor Quirino

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

nardnob
nardnob

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

Related Questions