简体   繁体   English

如何确定谁是对象的创建者

[英]How do I determine who is the creator of an object

I have a class that is called regularly by several objects. 我有一个由几个对象定期调用的类。 I would like to include information in any exceptions as who the creater of the object is. 我希望在任何例外中包含信息,如对象的创建者。 What are my options? 我有什么选择?

"Who" refers to an object or class “谁”指的是一个对象或类

Store a stacktrace when the constructor is called. 调用构造函数时存储堆栈跟踪。 This is similar to what SlimDX does in debug builds. 这与SlimDX在调试版本中的作用类似。

I might be missing something, but I am pretty sure that the only way you can do it, is by manually passing this information, fe. 我可能会遗漏一些东西,但我很确定你能做到的唯一方法就是手动传递这些信息,fe。 in constructor of your object. 在您的对象的构造函数中。
Edit : If this is what you were looking for? 编辑:如果这是你想要的? :


class Creator
{
    public string Name { get; private set; }

    public Creator(string name)
    {
        Name = name;
    }
}

class Foo
{
    readonly Creator creator;
    public Foo(Creator creator)
    {
        this.creator = creator;
    }

    public void DoSth()
    {
        throw new Exception("Unhandled exception. My creator is " + creator.Name);
    }
}

public static void Main()
{
    Foo f = new Foo(new Creator("c1"));
    f.DoSth();
}

If it's only for debugging purposes then add a local string field to the class and assign Environment.StackTrace to it in the class constructor. 如果它仅用于调试目的,则将一个本地字符串字段添加到类中,并在类构造函数中为其分配Environment.StackTrace Then you can include the information in the exceptions as well. 然后,您也可以将信息包含在例外中。

One choice would be to put a "parent" reference into the object: 一种选择是将“父”引用放入对象:

MyObject myObj = new MyObject(this);

and then use that. 然后使用它。

You can try to gather some information from the stack trace in the constructor of your object. 您可以尝试从对象的构造函数中的堆栈跟踪中收集一些信息。 You can get the stack frames StackTrace.GetFrames . 您可以获得堆栈帧StackTrace.GetFrames Then you can walk the stack and try to get the type that a method belongs. 然后,您可以遍历堆栈并尝试获取方法所属的类型。 If that type is different than the type of your object, you stop walking and store that type information within your object. 如果该类型与对象的类型不同,则停止行走并将该类型信息存储在对象中。 Then when an exception occurs, you can include that information along with the exception. 然后,当发生异常时,您可以包含该信息以及异常。

Note that this will increase the cost of instantiating your object. 请注意,这会增加实例化对象的成本。 So you should consider that and may be put in a mechanism to enable/disable it or include that piece of code only in the debug build. 因此,您应该考虑这一点,并且可以将其置于启用/禁用它的机制中,或仅在调试版本中包含该段代码。

The question is slightly ambiguous; 这个问题有点含糊不清; it really depends what you want. 这真的取决于你想要什么。 Is this debug information for debug builds, or is it something you will always keep around? 这是调试版本的调试信息,还是一直存在的东西?

If it's just debug cruft that will be removed in the released product , I'd suggest doing something like this to reduce the pollution of your class(es): 如果它只是在已发布的产品中删除的调试版本 ,我建议做这样的事情来减少你的课程的污染:

Move the creation into a factory and put the stack inspection code there. 将创建移动到工厂并将堆栈检查代码放在那里。 This way, the created class doesn't need to care about the stack frame stuff; 这样,创建的类不需要关心堆栈框架内容; it is hidden away in the factory. 它隐藏在工厂里。

You can then inject the information via a property setter if you don't mind a little pollution or you could have the factory update a list of created instances + associated creation information for each instance. 然后,如果您不介意有点污染,则可以通过属性设置器注入信息,或者您可以让工厂更新已创建实例的列表+每个实例的关联创建信息。 You can then query this list til your heart is content. 然后,您可以查询此列表,直到您满意为止。 Finally, in the release build, you can remove all of this functionality with a couple of #ifdefs. 最后,在发布版本中,您可以使用几个#ifdef删除所有这些功能。

I'd recommend using the StackTrace object and/or it's GetFrame method. 我建议使用StackTrace对象和/或它的GetFrame方法。 I haven't tried it but it should do what you need it to do w/o having to change every instantiation of the object (assuming you're not using a Factory). 我没有尝试过,但它应该做你需要做的事情而不必改变对象的每个实例化(假设你没有使用工厂)。

I would imagine something similar to this would work. 我会想象类似的东西会起作用。

using System.Diagnostics;
// get call stack
StackTrace stackTrace = new StackTrace();

// get calling method name
Console.WriteLine(stackTrace.GetFrame(1).GetMethod().Name);

Also note that this appears to be "not quite" a duplicate, but it's close to the question linked above. 另请注意,这似乎是“不完全”重复,但它接近上面链接的问题。

Something like this could work to get the calling type: 这样的东西可以用来获取调用类型:

public class Foo
{

    private Type ParentAtCreation = null;

    public Foo()
    {
        ParentAtCreation = (new StackTrace())
            .GetFrame(1)
            .GetMethod()
            .DeclaringType;
    }
}

You can use overloaded constructor to that class and a global variable to store that object you receive in that overloaded constructor 您可以将重载的构造函数用于该类,并使用全局变量来存储您在该重载的构造函数中接收的对象

eg if you want an object of class in winforms when you invoke the object to be created you use a overloaded constructor that receives an object of a form 例如,如果在调用要创建的对象时需要winforms中的类对象,则使用重载构造函数来接收表单的对象

and in the constructor you use this object to store its value in global variable like 在构造函数中,您使用此对象将其值存储在全局变量中

When you declare the object as in this case i use a form to open using my currently running form then 当你在这种情况下声明对象时,我使用一个表单来使用我当前运行的表单打开

Admin_Login ad = new Admin_Login(Enrol, this);
                ad.Show();
                this.Visible = false;

and make the current form not visible to invoke it again when i want it. 并使当前表单不可见,以便在我需要时再次调用它。 I cant dispose it as its the parent of the new form now 我现在无法将其作为新表格的父级处理

and in Admin_Login form i have an overloaded constructor 在Admin_Login表单中,我有一个重载的构造函数

public Admin_Login(string Enrol,Form parent)
    {
        Enrollment = Enrol;
        Parent = parent;
        InitializeComponent();
    }

where Parent is my global variable of Form 其中Parent是Form的全局变量

BOL BOL

I'm surprised no one else has said this yet, even as a caveat to their own solution, so I will: this is generally a bad idea, and if you find yourself needing to do it, that's usually a huge indicator that something is very wrong with your design. 我很惊讶没有其他人说过这个,即使是对他们自己的解决方案的一个警告,所以我会:这通常是一个坏主意,如果你发现自己需要这样做,那通常是一个巨大的指标,有些东西是你的设计非常错误。 If you go down this route to solve your problem, you will end up causing far larger issues down the road. 如果你沿着这条路走下去解决问题,最终会导致更大的问题。 Best to take 2 steps back and fix the design that is making this necessary. 最好采取两步,并修复使这必要的设计。

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

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