【问题标题】:Is it possible to have a make a generic method which can take the place of three methods with a System.Data.Linq.Mapping.FunctionAttribute?是否有可能制作一个通用方法,它可以用 System.Data.Linq.Mapping.FunctionAttribute 代替三个方法?
【发布时间】:2015-04-29 15:39:24
【问题描述】:

我的 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;
}

有什么方法可以编写一个泛型方法来传递要映射到的函数名吗?谢谢。

更新 因此,基于 Ron 和 Alex 的出色解决方案,我现在有了

/// <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);
}

【问题讨论】:

    标签: c# linq entity-framework datacontext function-attributes


    【解决方案1】:

    我会为代码重用做这样的事情:

    [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 构造的。

    【讨论】:

    • 看来我们的想法差不多+1
    • @Alex Indeed!,你也一样。
    • @RonBeyer 您可能想要删除其中一组参数
    【解决方案2】:

    有什么办法可以写一个泛型方法,其中函数名 映射到被传入?

    如果您指的是通用、“可重复使用”或“样板”:是的:

    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());
    }  
    

    【讨论】:

    • 我喜欢这里的 IdArgument 名称解决方案,并将在我的代码中通用方法需要引发参数异常的其他地方使用它。手感不错。
    猜你喜欢
    • 2014-12-14
    • 2020-08-05
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    相关资源
    最近更新 更多