user4593252
user4593252

Reputation: 3506

Iterate through list of ojects, instantiate, and call method on each without explicitly creating all

Suppose I have a bunch of classes in a WCF service to be exposed to a consumer. This list is enumerated in a method called clsServiceEnumertion.ListOfServices (returning Dictionary(string, Boolean)) within the WCF service. The list of available wrapped classes is stored in an enum in this service enumeration and they are enummed identically to the class name (such as clsEmailWrapper, clsPDFGenerator, and so forth). This way we can expose a reusable object as a service to multiple internally hosted websites (and internal software) without rewriting a lot of code, duplicating code, single point of updates, etc.

At any given time, the availability of any of these wrapped classes might be unavailable (due to maintenance, bug, discontinued, etc). This is controlled by the user in a configuration application. We also will not know ahead of time how many services will be there or what they will be called (a year from now there might be, say, 50). Services available and if they are enabled are stored in an xml file and bandied about the system in the form of Dictionary(string, boolean).

Sounds like a prime candidate for an iterator that would take advantage of the boolean. Problem: I only have string references to the service class which happen to be identical to the useful yet descriptively named bundled classes.

I know about reflection and activator but it's not fitting together into my head correctly. Can someone help me out on how to iterate through this dictionary, get the name of the class as a string if the boolean is true, create an object of that type and invoke the .Test method which will exist in all wrapped classes (the test method is to make sure that the service can run and will return a boolean while the iterator itself will store the name of the class and the results in a dictionary(string, boolean)).

I have everything except the actual iterator written.

  public Dictionary<string, Boolean> TestEnabledServices(Dictionary<string, Boolean> listOfEnabledServices)
    {
        Dictionary<string, Boolean> resultSet = new Dictionary<string, bool>();
        foreach (KeyValuePair<string, Boolean> pair in listOfEnabledServices)
        {
            if (pair.Value)
            {
                Boolean retVal = false;
                //TODO: actual test here
                retVal = true ? true : false; //the result of the test...

                resultSet.Add(pair.Key, retVal);
            }//end if
        }//end foreach

        return resultSet;
    }//end TestEnabledService

Upvotes: 0

Views: 108

Answers (1)

Zache
Zache

Reputation: 1043

I think this is what you want

Dictionary<string, bool> GetEnabledAndTestedServices(Dictionary<string, bool> input)
{
    var testedServices = new Dictionary<string, bool>();
    foreach(var kvp in input)
    {
        if(!kvp.Value) //disabled
            continue;

        var type = Type.GetType(kvp.Key);

        if(type == null)
            throw new Exception("This service does not exist!");

        var instance = Activator.CreateInstance(type);

        // if the Test() method is part of an interface
        // public interface ITestableService { bool Test() }
        // and it's implemented by all services we can do this:
        var service = instance as ITestableService;
        if(service != null)
        {
            if(service.Test())
                testedServices.Add(kvp.Key, true);
        } 
        else //Otherwise we call it via reflection, you could also do dynamic
        {
            var testMethod = type.GetMethod("Test");
            if(testMethod == null)
                throw new Exception("The service is not testable");

            var testResult = testMethod.Invoke(instance, null) as bool?;
            if(testResult.HasValue && testResult.Value)
                testedServices.Add(kvp.Key, true);
        }
    }

    return testedServices;
}

Upvotes: 2

Related Questions