Simplify code with sending Methods as Variable

170 Views Asked by At

I want to load XML into my program.

most parts of code have same body with a little difference.

this part is used in many methods.but with a bit differences.

        while (reader.Read())
        {
            if (StateElement(State.Enter, "EnterElement", reader))// "EnterElement" is Variable
            {
                LoadElement(reader, type);// Method LoadElement and type are variables
            }
            else if (StateElement(State.Exit, "ExitElement", reader))//"ExitElement" is Variable
            {
                break;
            }
        }

If i be able to put this part inside Method it will save lots of lines and become very simplified and readable.

i wish i could have something like this method.

    private void ReadElement(XmlTextReader reader,string enterElement,string exitElement,LoadElement(reader, type))
    {
        while (reader.Read())
        {
            if (StateElement(State.Enter, enterElement, reader))
            {
                LoadElement(reader, baseType);
            }
            else if (StateElement(State.Exit, exitElement, reader))
            {
                break;
            }
        }
    }

And then to Call it :

ReadElement(reader,"EnterElement","ExitElement",LoadElement(reader,type));

is this possible? (this way is not possible but is there any way to send method as variable?)

Solved:

thanks for the answers. here is my method with delegate.

    private void ReadElement(XmlTextReader reader, string enterElement, string exitElement, object type, Delegate loadElement)
    {
        while (reader.Read())
        {
            if (StateElement(State.Enter, enterElement, reader))
            {
                loadElement.DynamicInvoke(type);
            }
            else if (StateElement(State.Exit, exitElement, reader))
            {
                return;
            }
        }
    }

and the way to call it:

        ReadElement(reader, "enterElement", "exitElement", baseType, (Action<BaseType>)(type => // or (Action)(() => for no arguments.
        {
            LoadElement(reader, type);
        }));

LoadElement can be void Now.

Since i call in every method i pass method and variables directly into delegate so it will be even more simple.

private void ReadElement(XmlTextReader reader, string enterElement, string exitElement, Action loadElement)

and instead of DynamicInvoke i use Invoke witch is faster.

also the calls would be:

        ReadElement(reader, "EnterElement", "ExitElement", () =>
        {
            LoadElement(reader, baseType);//basetype and reader will be passed to delegate by the current method that is calling ReadElement 
        });
2

There are 2 best solutions below

1
On BEST ANSWER

Using Delegates it the most common way to pass a Function as a parameter into a function

I don't know what type is but you could use a Delegate. This would work for everything. If you have a more specific function you could use Action<...> or Func<...> or a specific delegate

piravte void ReadElement(XmlTextReader reader,string enterElement,string exitElement, Delegate LoadElement, object yourReader, object yourType))
{
    while (reader.Read())
        {
            if (StateElement(State.Enter, enterElement, reader))
            {
                LoadElement.DynamicInvoke(yourReader, yourType);
            }
            else if (StateElement(State.Exit, exitElement, reader))
            {
                break;
            }
        }
}

Call ReadElement like:

ReadElement(yourReader, yourEnterElement, yourExitelement, (Action<string, dataTypeOfType>)((yourReader, yourType) => 
    { 
        // Whatever you want to do in LoadElement 
        // Use yourReader and yourType as the Parameter of your Function
    }));
4
On

What youre looking for are delegates:

https://msdn.microsoft.com/en-us/library/ms173171.aspx

In short, a delegate functions as a placeholder for another method or function. Calling the delegate placeholder delegates the call to whatever the delegate is pointing at. This is a gross oversimplification, its an area that really requires further reading.

In your specific case, you can use an Action delegate. You can call the delegate just like a method, and your new method would look like this:

private void ReadElement(XmlTextReader reader,string enterElement,string exitElement,Action<XmlTextReader, Type> action)
{
    while (reader.Read())
    {
        if (StateElement(State.Enter, enterElement, reader))
        {
            action(yourReader, yourType);
        }
        else if (StateElement(State.Exit, exitElement, reader))
        {
            break;
        }
    }
}