听取对象实例化

时间:2017-07-26 14:02:17

标签: c# .net object garbage-collection

我有接口和一些实现此接口的类。 我想监听任何将被实例化的对象,并检查该对象是否实现了我的接口。

我的主要原因是存储对这种对象的所有引用,并简单地调用所有对象的接口方法。

2 个答案:

答案 0 :(得分:1)

正如Kyle在评论中所说,抽象类的构造函数将是最佳选择。或者必须用于建造这类物体的工厂。

但是,如果这不是一个选项,则可以采用以下方法。

如果"听众"可以全局访问(例如静态),可以向其中添加Register(IYourInterface obj)Unregister(IYourInterface obj)等方法,并确保实现该接口的每个类都将在构造/解构时调用这些方法。不是最干净的方式,但只要你保持这种行为,它就会起作用。

示例:

public static class Listener
{
    private static List<IMyInterface> objects = new List<IMyInterface>();

    public static void Register(IMyInterface obj)
    {
        if (!objects.Contains(obj))
            objects.Add(obj);
    }

    public static void Unregister(IMyInterface obj)
    {
        if (objects.Contains(obj)
            objects.Remove(obj);
    }

    public static void DoSomethingWithObjects()
    {
        foreach (IMyInterface obj in objects)
            // do something ...
    }
}

public class SomeTestClass : IMyInterface
{
    public SomeTestClass()
    {
        Listener.Register(this);
    }
}

答案 1 :(得分:0)

有几种方法可以解决这个问题。

使用基本抽象类

最简单的解决方案是拥有一个继承自的基类。这种方式违背了界面的目的,但这是您可以添加此类代码进行创建的唯一方法。你可以这样做:

public abstract class AbstractBaseClass
{
    public AbstractBaseClass()
    {
        ObjectRegister.StoreReference(this);
    }

    public abstract void MethodToCall();
}

public class SubClass : AbstractBaseClass
{
    public SubClass() : base() //Don't forget 'base()'!
    {
        //Your code here
    }

    public override void MethodToCall()
    {
        Console.WriteLine("Called in SubClass");
    }
}

如果要提供默认操作,抽象MethodToCall也可以是虚拟的,但如果它是抽象的,编译器会抱怨您没有以类似于接口的方式实现它。

使用公共静态实例化方法

有点冗长,但在Unity之类的东西中可以看到。在这种情况下,您没有执行x = new Y(),而是使用公共静态方法(可能是通用方法),为您创建类,注册它,然后返回该实例。假设您的界面被称为&#39; IRegisterable&#39;,您可能会有以下内容:

public static class ObjectRegister
{
    //Note the 'where', which constrains T to be something that
    //implements IRegisterable 
    public static T Instantiate<T>() where T:IRegisterable
    {
        T obj = new T();
        StoreReference(obj);
        return obj;
    }

    private static StoreReference(IRegisterable obj)
    {
        //Do your storing code here. This doesn't even need to be a method
        //if your reference storing stuff only happens on object creation
    } 
}

//Elsewhere, where class 'Thing' implements IRegisterable

Thing x = ObjectRegister.Instantiate<Thing>();
//x is now registered. No need to do x = new Thing()

string y = ObjectRegister.Instantiate<string>();
//Error: string does not implement IRegisterable

不幸的是,以这种方式提供构造函数参数并不容易。你可以使用一个Init()方法,但它可以作为一种伪造构函数。