2012-03-06 10 views
7

estoy usando el siguiente momento:Uso variable en lugar del nombre de la función

foreach (string file in files) { 
    switch (filetype.Value) { 
     case "ReadFile": 
      ReadFile(file); 
      break; 
     case "ReadMSOfficeWordFile": 
      ReadMSOfficeWordFile(file); 
      break; 
     case "ReadMSOfficeExcelFile": 
      ReadMSOfficeExcelFile(file); 
      break; 
     case "ReadPDFFile": 
      ReadPDFFile(file); 
      break; 
    } 
} 

Funciona, pero se siente un poco mal. La forma en Python sería algo más parecido a esto:

foreach string file in files: 
    filetype.Value(file) 

tengo un momento muy difícil imaginar que C# no se puede hacer algo como esto. Puede ser que mis habilidades de Google sean malas, pero parece que no puedo resolverlo.

SOLUCIÓN

public static readonly IDictionary<string, Action<string>> FileTypesDict = new Dictionary<string,Action<string>> { 
    {"*.txt", ReadFile}, 
    {"*.doc", ReadMSOfficeWordFile}, 
    {"*.docx", ReadMSOfficeWordFile}, 
    {"*.xls", ReadMSOfficeExcelFile}, 
    {"*.xlsx", ReadMSOfficeExcelFile}, 
    {"*.pdf", ReadPDFFile}, 
}; 

 

foreach (KeyValuePair<string, Action<string>> filetype in FileTypesDict) { 
    string[] files = Directory.GetFiles(FilePath, filetype.Key, SearchOption.AllDirectories); 
    //System.Reflection.MethodInfo ReadFileMethod = ReadFile.GetType().GetMethod(filetype.Value); 
    foreach (string file in files) { 
     FileTypesDict[filetype.Key](file); 
    } 
} 
+0

I lo siento pero no puedo descifrar qué es filetype? –

+1

Considere hacer que los valores de los cambios sean enum en lugar de cadena. No es una solución a su problema, pero es una buena práctica para asegurarse de detectar errores en el tiempo de compilación. – Stilgar

+0

Muéstrenos la forma en que obtiene/construye '' fileType''s. Posiblemente un cambio menor allí (que proporciona un delegado en lugar de una cadena) hace que todo desaparezca fácilmente. –

Respuesta

8

Puede hacerlo con un poco de preparación utilizando los delegados, así:

private static readonly IDictionary<string,Action<string>> actionByType = 
    new Dictionary<string,Action<string>> { 
     {"ReadFile", ReadFile} 
    , {"ReadMSOfficeWordFile", ReadMSOfficeWordFile} 
    , {"ReadMSOfficeExcelFile", ReadMSOfficeExcelFile} 
    , {"ReadPDFFile", ReadPDFFile} 
    }; 

Cuando es el momento de llamar a su acción , hazlo de la siguiente manera:

actionByType[actionName](file); 
+0

Python puede hacerlo porque es un lenguaje dinámico. Aunque C# tiene soporte para tipos dinámicos, no es un lenguaje dinámico. Es por eso que necesita usar algo como esto – linkerro

+0

Me gusta, pero veo el error: Error Argumento '2': no ​​se puede convertir de 'grupo de métodos' a 'System.Action ' – MTeck

+0

@MTeck ¿Sus métodos 'XYZFile (...)' tienen todos la misma firma? ¿Toman 'RegularExpressions.Group'? Además, ¿sus métodos 'XYZFile (...)' son estáticos? – dasblinkenlight

4

se podía mantener un Dictionary de delegados, como la forma más sencilla:

Dictionary<string, Action<string>> fileReaders = new Dictionary<string, Action<string>>() { 
    {"ReadFile", ReadFile}, 
    {"ReadOfficeWordFile", ReadOfficeWordFile}, 
    {"ReadOfficeExcelFile", ReadOfficeExcelFile}, 
    {"ReadPDFFile", ReadPDFFile} 
}; 

A continuación, llame así:

fileReaders[fileType.Value](file); 

Dependiendo de lo que regresan a sus métodos, es posible que tenga para cambiar el tipo de delegado (Action<string> significa void something(string someparam) como firma de método, por ejemplo) también.

6

Puede utilizar un delegado:

Action<string> action; 
switch (filetype.Value) { 
    case "ReadFile": 
    action = ReadFile; 
    break; 
    case "ReadMSOfficeWordFile": 
    action = ReadMSOfficeWordFile; 
    break; 
    case "ReadMSOfficeExcelFile": 
    action = ReadMSOfficeExcelFile; 
    break; 
    case "ReadPDFFile": 
    action = ReadPDFFile; 
    break; 
    default: 
    throw new NotImplementedException("Unhandled file type '"+filetype.Value+"'."); 
} 
foreach (string file in files) { 
    action(file); 
} 
1

También podría utilizar la reflexión (si estás bien con los diferentes sobrecarga que puede traer) Marque esta solution

esperanza de que ayudó

2

Creo que lo que está buscando necesitará alguna refacturación de su código.

Todos sus "casos" (TextFile, MSOfficeWordFile, MSOfficeExcelFile, PdfFile) deben ser sus propias clases que implementan una interfaz única.

Su interfaz debe denominarse como "IReadableFile" y especificar un método llamado "ReadFile()".

Cada clase debe tener su propia implementación de "ReadFile()"

Ejemplo:

public interface IReadableFile 
{ 
    void ReadFile(); 
} 

public class MSOfficeWordFile : IReadableFile 
{ 
    public void ReadFile() 
    { 
     ReadMSOfficeWordFile(file); 
    } 
} 

foreach(IReadableFile file in files) 
    file.ReadFile(); 

Código puede contener algunos errores, pero Espero que entiendas la idea.

0

Si usted está buscando una manera de evitar la asignación explícita de los nombres de los métodos a los valores de cadena que puede utilizar la reflexión para hacer la invocación método dinámico (esto supone filetype.Value es de tipo String)

String method_name = String.Empty; 
foreach (string file in files) { 
    method_name = filetype.Value; 
    System.Reflection.MethodInfo method = this.GetType().GetMethod(method_name); 
    method.Invoke(this, new object[]{file}); 
} 
Cuestiones relacionadas