Можно ли создать универсальный метод, который может заменить три метода с System.Data.Linq.Mapping.FunctionAttribute?

У меня есть три метода в моем классе datacontext, которые все вызывают немного отличающиеся хранимые процедуры, имеющие различное поведение; ПРИЛОЖЕНИЕ, ОБНОВЛЕНИЕ, ПЕРЕЗАПИСЬ. Однако все три метода по сути имеют один и тот же код. Единственным отличием является свойство "Имя" System.Data.Linq.Mapping.FunctionAttribute который украшает методы.

[Function(Name = "import.usp_MyData_ProcessImportAppend", IsComposable = false)]

или же

[Function(Name = "import.usp_MyData_ProcessImportUpdate", IsComposable = false)]

или же

[Function(Name = "import.usp_MyData_ProcessImportOverwrite", IsComposable = false)]

По сути, все они похожи на это

/// <summary>
/// Processes the import.
/// </summary>
/// <param name="loadId">The load id.</param>
/// <exception cref="System.ArgumentNullException">loadId</exception>
[Function(Name = "import.usp_MyData_ProcessImportAppend", IsComposable = false)]
public Int32 ProcessGradingImport(string loadId)
{
    // Validate parameter
    if (String.IsNullOrEmpty(loadId)) throw new ArgumentNullException("loadId");

    // Initialise the result and the procedure parametes
    Int32 result = 0;
    object[] parameters = { loadId };

    // Call the procedure, and return the result
    IExecuteResult executionResult = ExecuteMethodCall(this, (MethodInfo)(MethodBase.GetCurrentMethod()), parameters);
    if (executionResult != null) result = (int)executionResult.ReturnValue;
    return result;
}

Можно ли как-нибудь написать общий метод, в котором передается имя функции для сопоставления? Спасибо.

ОБНОВЛЕНИЕ Итак, благодаря превосходным решениям Рона и Алекса, теперь у меня есть

/// <summary>
/// Process imports.
/// </summary>
/// <param name="methodInfo">The method information.</param>
/// <param name="loadId">The load identifier.</param>
/// <returns></returns>
/// <exception cref="System.ArgumentNullException">loadId</exception>
private Int32 ProcessImport(MethodInfo methodInfo, string loadId)
{
    // Validate parameter
    if (String.IsNullOrEmpty(loadId)) throw new ArgumentNullException("loadId");

    // Initialise the result and the procedure parametes
    Int32 result = 0;
    object[] parameters = { loadId };

    // Call the procedure, and return the result
    IExecuteResult executionResult = ExecuteMethodCall(this, methodInfo, parameters);
    if (executionResult != null) result = (int)executionResult.ReturnValue;
    return result;
}

называется в украшенной функции, как...

[Function(Name = "common.usp_MyData_ProcessImportAppend", IsComposable = false)]
public Int32 ProcessImportAddNewUpdateCurrentOnly(string loadId)
{
    return ProcessImport((MethodInfo)(MethodBase.GetCurrentMethod()), loadId);
}

2 ответа

Решение

Я бы сделал что-то вроде этого для повторного использования кода:

[Function(Name = "import.usp_MyData_ProcessImportAppend", IsComposable = false)]
public Int32 ProcessGradingImport(string loadId)
{
    ProcessLoadId(loadId, (MethodInfo)(MethodBase.GetCurrentMethod(), new object[] { loadId });
}

[Function(Name = "import.usp_MyData_ProcessImportUpdate", IsComposable = false)]
public Int32 ProcessGradingImportUpdate(string loadId)
{
    ProcessLoadId(loadId, (MethodInfo)(MethodBase.GetCurrentMethod(), new object[] { loadId });
}

[Function(Name = "import.usp_MyData_ProcessImportOverwrite", IsComposable = false)]
public Int32 ProcessGradingImportOverwrite(string loadId)
{
    ProcessLoadId(loadId, (MethodInfo)(MethodBase.GetCurrentMethod(), new object[] { loadId });
}

public Int32 ProcessLoadId(string loadId, MethodInfo method, object[] parameters)
{
    // Validate parameter
    if (String.IsNullOrEmpty(loadId)) throw new ArgumentNullException("loadId");

    // Initialise the result and the procedure parametes
    Int32 result = 0;

    // Call the procedure, and return the result
    IExecuteResult executionResult = ExecuteMethodCall(this, methodInfo, parameters);
    if (executionResult != null) result = (int)executionResult.ReturnValue;
    return result;
}

К сожалению, в C# 5.0 нет способа сделать то, что вы просите. Атрибут не допускает нескольких копий для каждой функции, поэтому все, что вы можете сделать, это выделить повторный код и немного его разложить. Вероятно, его можно уменьшить, чтобы удалить объект параметров, так как он только что создан из loadId тем не мение.

Можно ли как-нибудь написать общий метод, в котором передается имя функции для сопоставления?

Если вы имеете в виду под общим, "многоразовым" или "шаблонным": yes:

private Int32 MyBoilerplateImpl(string IdArgument, string argumentName, MethodInfo method)
{
    // Validate parameter
    if (String.IsNullOrEmpty(IdArgument)) throw new ArgumentNullException(argumentName);

    // Initialise the result and the procedure parameters
    Int32 result = 0;
    object[] parameters = { IdArgument};

    // Call the procedure, and return the result
    IExecuteResult executionResult = ExecuteMethodCall(this, method, parameters);
    if (executionResult != null) 
        result = (int)executionResult.ReturnValue;
    return result;
}

И вызвать это как:

[Function(Name = "import.usp_MyData_ProcessImportAppend", IsComposable = false)]
public Int32 ProcessGradingImport(string loadId) 
{
    MyBoilerplateImpl(loadId, "loadId", (MethodInfo)(MethodBase.GetCurrentMethod());
}  
Другие вопросы по тегам