简体   繁体   English

C#拦截构造函数参数

[英]c# Intercept constructor parameters

I am attempting to write a job queuing system using C#. 我正在尝试使用C#编写作业排队系统。

Suppose I have the following class which represents a job to perform at a later date: 假设我有以下课程,它代表以后要执行的工作:

  public class TestJob : QueuableJob
    {
        private readonly string _t;
        private readonly string _e;
        public TestJob(string t, string e)
        {
            _t = t;
            _e = e;

        }
        public Task PerformWork(ITestService testService)
        {
            testService.Message($"Hello: {_t} {_e}");
            return Task.CompletedTask;
        }
    }

I would like to be able to call something like: 我希望能够打电话给类似的人:

JobQueueService.EnqueueJob(new TestJob("value1", "value2"));

In order to queue a job, I need serialize the parameters passed to the constructor of TestJob , so I can store them in a persistence layer (eg a database) and later deserialize them. 为了使作业排队,我需要序列化传递给TestJob的构造函数的TestJob ,以便将它们存储在持久层(例如数据库)中,然后反序列化它们。 Then I can instantiate the class and execute PerformWork . 然后,我可以实例化该类并执行PerformWork I would like to handle this as seamless as possible in my library so the end-user writing their "Job" classes doesn't have to worry about adding specific things for serialization. 我想在我的库中尽可能无缝地处理此问题,因此编写“ Job”类的最终用户不必担心要添加用于序列化的特定内容。

I cannot figure out a way to "intercept" the parameters passed to the TestJob class without either losing strict typing (eg I could use params object[] parameters ), or forcing the end user to implement some other code to help with serialization. 我无法想出一种方法来“拦截”传递给TestJob类的参数而不丢失严格的键入(例如,我可以使用params object[] parameters ),或者强迫最终用户实现一些其他代码来帮助序列化。

Currently, the most elegant solution I can think of (for the end user), is something like this: 目前,我能想到的(对于最终用户)最优雅的解决方案是这样的:

public class TestJob : QueuableJob
    {
        private readonly string _t;
        private readonly string _e;
        public TestJob(string t, string e) : base(t,e)
        {
            _t = t;
            _e = e;

        }
        public Task PerformWork(ITestService testService)
        {
            testService.Message($"Hello: {_t} {_e}");
            return Task.CompletedTask;
        }
    }

However, that would require the developer to remember to pass all of their parameters to base() (like base(t,e) in the example above). 但是,这将要求开发人员记住将其所有参数传递给base()(就像上面示例中的base(t,e) )。 The compiler will not complain if they forget to do this, so it could be source of tricky bugs. 如果他们忘记这样做,编译器将不会抱怨,因此它可能是棘手的错误的来源。 I've also tried to get the information using System.Diagnostics.StackTrace in the QueuableJob constructor, however it don't believe I can obtain the values of the parameters from the stack. 我还尝试使用QueuableJob构造函数中的System.Diagnostics.StackTrace获取信息,但是它不相信我可以从堆栈中获取参数的

Is there any way I can use reflection to "intercept" what is being passed into the TestJob constructor? 有什么方法可以使用反射来“拦截”传递给TestJob构造函数的内容?

I'm not sure I think this is necessarily the best way to approach the problem, but since you know more about this problem than I do, here is a way to get the names of the constructor parameters for a type: 我不确定我认为这一定是解决问题的最佳方法,但是由于您比我了解更多有关此问题的信息,因此这里提供了一种获取类型的构造函数参数名称的方法:

var constructors = typeof(TestJob).GetConstructors();
var constructor = constructors[0];
foreach (var param in constructor.GetParameters())
{
    Console.WriteLine($"Argument: {param.Position} is called {param.Name} and is a {param.ParameterType}");
}

Likewise, you can use reflection to retrieve the values on runtime and use Activator.CreateInstance to instantiate the objects again. 同样,您可以使用反射在运行时检索值,并使用Activator.CreateInstance再次实例化对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM