将对象传递给方法而不向方法添加参数?

时间:2016-03-17 03:35:01

标签: c# methods

我有一个名为IEvent的简单接口,它只包含这一个方法:

void Execute();

我有几个来自此接口的派生类,其中一个需要访问方法调用者拥有的对象。该对象以这种方式使用:

using (MyObject object = new MyObject(this.MessageService)
{
    foreach (IEvent myEvent in eventList)
    {
        myEvent.Execute(); // <--- I need to pass object without adding argument here if possible?
    }
}

我会将对象添加为需要访问它的派生类中的字段,但是当我到达这部分代码时,IEvent对象已经构建并在后台线程上运行。目前,我能想到的唯一方法是在IEvent界面中为这个对象添加一个setter,但后来我暴露了一个大多数派生类都不会关心并且看起来不干净的字段溶液

我会将它作为一个参数添加到Execute(),但问题是该对象属于一个程序集,包含IEvent的程序集不知道(并且不想让它知道无论如何,99%的事件都不关心这个对象。有没有更好的方法来完成我在这里尝试做的事情?

2 个答案:

答案 0 :(得分:0)

我将搭载Jon Skeet's amazing knowledge of C#,.NET,CLR,IL以及围绕这些主题的所有内容。您无法访问调用对象的实例,尤其是调用方法中的本地变量。您可以获取其类型,您可以通过StackTrace获取调用方法,例如(StackTrace.GetFrames()),但在这种情况下,这些都不会对您有任何帮助。您要完成的任务需要大量深入调试API。至于走栈,这是我创建的一个快速示例,试着看看我是否可以为你找出一些东西(我假设你的程序是如何构建的......显然它不是一对一的样本):< / p>

using System;
using System.Collections.Generic;
using System.Diagnostics;

namespace SampleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var eventList = new List<IEvent> { new SomeClass() };

            using (MyObject obj = new MyObject(new MessageService()))
            {
                foreach (IEvent myEvent in eventList)
                {
                    myEvent.Execute();
                }
            }
        }
    }

    public interface IEvent
    {
        void Execute();
    }

    public class SomeClass : IEvent
    {
        public void Execute()
        {
            var stackTrace = new StackTrace();
            var stackFrames = stackTrace.GetFrames();
            var callingMethod = stackFrames[1].GetMethod();
            var callingType = callingMethod.DeclaringType;
        }
    }

    public class MyObject : IDisposable
    {
        public MessageService Service { get; }

        public MyObject(MessageService service)
        {
            Service = service;
        }

        public void Dispose()
        {
            Service.Stop();
        }
    }

    public class MessageService
    {
        public void Start() { }
        public void Stop() { } 
    }
}

我喜欢你的问题,因为它提出了一个有趣且不寻常的情况,但我担心如果不超出C#在其武器库中的常规惯例,你将无法完成任务。您可以使用非托管代码来解决问题,但这完全是另一个主题。

然而,除了它是一个有趣的问题...看看你想要做什么。您有MyObject,它显然会实现IDisposable,并会在Dispose()语句的末尾调用using,并且您尝试从其他程序集中获取其引用。我认为这不是一个好主意。

我建议您重新访问您的设计并使用可选参数等内容。可能不是适合您情况的“完美”解决方案,因为您将其传递给Execute循环中的每个foreach,但它最好跳过一千个调试API的箍。

答案 1 :(得分:0)

  

“如果实现IEvent的类没有/不能以IEvent中声明的方式实现IEvent指定的所有方法,那么该类应该不首先实施IEvent。“ - 清扫车

所以你的整个程序设计可能有问题。我认为你最好稍微修改你的设计并改变类和接口之间的一些关系。

如果您不想这样做,还有另一种(不推荐)方法可以解决此问题。

假设您的方法调用者属于MethodCaller类型。您只需将界面中Execute的声明更改为:

void Execute(MethodCaller obj = null);

实现IEvent的所有类都可以忽略您在问题中提到的类之外的参数。