Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不考虑PARM数量的重用逻辑的模式_C#_Logging - Fatal编程技术网

C# 不考虑PARM数量的重用逻辑的模式

C# 不考虑PARM数量的重用逻辑的模式,c#,logging,C#,Logging,我想在几个方法之前和之后调用一些日志逻辑。每个方法接受不同数量/类型的参数。我正在尝试设置它,以便在调用每个方法时不必重复日志逻辑。我已经能够通过创建一些代理来减少重复的数量。我已经为使用的每种数量/类型的PARM创建了一个委托,并且我有一个接受每个委托并进行日志记录的方法。然而,我仍然有大约6个不同的代表,因此这6个代表的逻辑是重复的 我认为需要修改它,所以不管parm的数量如何,我有一个方法来记录日志并调用该方法。但我还没弄明白 下面是一个代表的例子和我不想重复的逻辑 public

我想在几个方法之前和之后调用一些日志逻辑。每个方法接受不同数量/类型的参数。我正在尝试设置它,以便在调用每个方法时不必重复日志逻辑。我已经能够通过创建一些代理来减少重复的数量。我已经为使用的每种数量/类型的PARM创建了一个委托,并且我有一个接受每个委托并进行日志记录的方法。然而,我仍然有大约6个不同的代表,因此这6个代表的逻辑是重复的

我认为需要修改它,所以不管parm的数量如何,我有一个方法来记录日志并调用该方法。但我还没弄明白

下面是一个代表的例子和我不想重复的逻辑

    public delegate void LineOfBusinessHandler(DateTime runDate, LineOfBusinessCode lineOfBusinessCode);

    public void Run(DateTime runDate, ProcessCode process, LineOfBusinessCode lineOfBusinessCode, LineOfBusinessHandler del)
    {
        this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Started.ToString(), null, runDate);


        try
        {
            del(runDate, lineOfBusinessCode);
            this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Finished.ToString(), null, runDate);
        }
        catch (Exception e)
        {
            int errorId = SystemManager.LogError(e, process.ToString());
            this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Errored.ToString(), errorId, runDate);
        }
    }

如果我正确理解了你的问题,听起来你可以使用C#params关键字。有关如何使用它的参考信息,请参见:

使用参数时的一个要求是必须将其放在函数签名的最后。然后,在函数内部,您可以枚举和迭代变量参数列表,就像它是一个数组一样

编辑

要扩展@Ben Voigt发布的评论,使用params关键字的另一个限制是它要求变量参数列表的类型相同。但是,在您的情况下,这可以减轻,因为您只关心日志记录。在本例中,您可能会对需要记录的对象调用ToString()方法,以便创建object类型的变量参数列表

如果调用ToString()是不够的,并且您有不同类型的对象,您可以使所有这些对象实现一个公共接口。让我们称之为
ilogableobject
,它公开了一个提供日志输出的方法。如果您能够更改这些对象,则可以这样做。

C语言没有任何元编程语法。你必须使用反射。您当然可以对任意方法/委托进行反思,以确定参数类型,然后构建一个记录参数并调用原始方法的方法,编译这个新的包装器方法,并返回一个与原始方法具有相同调用签名的委托

您可以在运行时执行此操作(返回一个委托),或者使用所有包装函数构建一个新的程序集,然后代码可以引用该程序集并正常使用

您应该了解用于面向方面编程的代码编织工具。他们中的一些人已经这样做了


与使用params数组不同,这将为您提供一个与原始方法具有相同签名(或委托类型)的包装器,因此它是类型安全的,Intellisense可以工作(与任何其他委托一样)。

这取决于不同版本之间的共同点,但假设runDate和process是共同的,您可以这样做:

public void Run(DateTime runDate, ProcessCode process, LineOfBusinessCode lineOfBusinessCode, LineOfBusinessHandler del)
{
    this.DoRun(runDate, process, (d, p) => del(d, p, lineOfBusinessCode));
}

public void DoRun(DateTime runDate, ProcessCode process, Action<DateTime, ProcessCode> action)
{
    this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Started.ToString(), null, runDate);


    try
    {
        action(runDate, process);
        this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Finished.ToString(), null, runDate);
    }
    catch (Exception e)
    {
        int errorId = SystemManager.LogError(e, process.ToString());
        this.ProcessManager.AddToBatchLog(process.ToString(), ProcessStatus.Errored.ToString(), errorId, runDate);
    }
}
public void Run(日期时间运行日期、流程代码流程、业务代码行、业务处理程序行)
{
DoRun(运行日期,进程,(d,p)=>del(d,p,业务代码行));
}
public void DoRun(日期时间运行日期、流程代码流程、操作)
{
this.ProcessManager.AddToBatchLog(process.ToString(),ProcessStatus.Started.ToString(),null,runDate);
尝试
{
操作(运行日期、进程);
this.ProcessManager.AddToBatchLog(process.ToString(),ProcessStatus.Finished.ToString(),null,runDate);
}
捕获(例外e)
{
int errorId=SystemManager.LogError(e,process.ToString());
this.ProcessManager.AddToBatchLog(process.ToString(),ProcessStatus.Errored.ToString(),errorId,runDate);
}
}
您甚至可以进行泛化,这样就不必这样定义自定义委托:

public void Run<T1>(DateTime runDate, ProcessCode process, T1 param1, Action<DateTime, ProcessCode, T1> del)
{
    this.DoRun(runDate, process, (d, p) => del(d, p, param1));
}

public void Run<T1, T2>(DateTime runDate, ProcessCode process, T1 param1, T2 param2, Action<DateTime, ProcessCode, T1, T2> del)
{
    this.DoRun(runDate, process, (d, p) => del(d, p, param1, param2));
}
public void运行(DateTime runDate,ProcessCode进程,T1参数1,Action del)
{
DoRun(runDate,process,(d,p)=>del(d,p,param1));
}
public void运行(DateTime runDate、ProcessCode进程、T1参数1、T2参数2、Action del)
{
DoRun(runDate,process,(d,p)=>del(d,p,param1,param2));
}

我意识到这可能超出了您所寻找的范围和/或能力。但是,如果您有一个通用的日志逻辑,希望在不同的方法调用上重用,而不丢失类型安全性(即不在
对象[]
中传递参数),那么方法就是拦截。您需要一个能够提供AOP、依赖注入或类似功能的框架(我不建议您首先编写自己的框架!)。这些东西通常可以处理拦截

例如,我有一个用于Ninject的日志拦截器:

public void Intercept(IInvocation invocation)
{
    var logger = LoggerFactory.GetLogger(invocation.Request.Method.DeclaringType);
    var debug = !invocation.Request.Method.IsSpecialName && logger.IsDebugEnabled;
    if (debug)
        logger.Debug(invocation.Request.Method.Name);
    try
    {
        invocation.Proceed();
        if (debug)
            logger.Debug(invocation.Request.Method.Name + " FINISH");
    }
    catch (Exception)
    {
        logger.Error(invocation.Request.Method.Name + " ERROR");
        throw;
    }

}
然后,我通过使用Ninject获取对象(如果您不知道,请查看一些),同时向对象添加一些拦截来创建对象,例如:
Kernel.Bind().ToSelf().Intercept().with()其中
LoggingInterceptor
使用上述方法实现
IInterceptor

只要说你需要更多的细节帮助


编辑:刚刚意识到我的示例没有显示这一点,但是您也可以访问调用的参数(作为对象集合)

当参数都是不同的类型时,这有什么帮助?@Ben Voigt-您创建类型object的变量参数列表。非常类似于Console.Write()函数的签名。因为这是用于日志记录的,所以您可能只需要在它们上调用ToString。但是它们仍然需要传递给真正的函数。@Ben Voigt-也许我不理解他的问题。。我认为他控制(设计)了日志框架。请看那一行
del(runDate,lineOfBusinessCode)
。这需要在记录调用之间完成,转发传入的参数。如果丢失了参数的类型