-->

Self-proxying constructor with Castle?

2019-08-29 03:59发布

问题:

Is it possible for a class's constructor to wrap a proxy around itself? This code, unfortunately, causes a StackOverflowException.

void Main()
{
    var thing = new Thing();
}

public static readonly ProxyGenerator generator = new ProxyGenerator();

public class Thing
{
    public Thing()
    {
        generator.CreateClassProxyWithTarget(this);
    }
}

I want some way to guarantee that new instances of my class are wrapped in the proxy instead of having to create some kind of factory that creates proxied instance.

回答1:

As far as I know, what you want is not supported. If you have a public, parameter-less constructor, anyone can create your class.

Now, that doesn't mean you can't get what you want -- it'll just be a bit more work. You could have an "initialized" flag on the class that is scoped as internal (only classes in your assembly can access it). A factory would be used to create the proxied instance and set the initialized flag to true. Only the factory will set this flag. Every public method in your class could execute a check to make sure the "initialized" flag is true and throw an exception if its false (this is where the "more work" comes in -- you'll have to manually add this check to every method). The new'd up instances can't set the initialized flag because of it's scope.

This won't prevent someone from new-ing up one of your classes, but it will at least prevent them from using it. As for serialization, you'll probably want to have some data-only classes and serialize those instead of your proxied classes.



回答2:

The closest that I have come is creating a Singleton that returns a proxy. Here is an example:

public class MySingleton
{
    protected static MySingleton _instance = null;
    public static MySingleton Instance
    {
        get
        {
            if (_instance == null)
            {
                if (Simple.UseDynamicProxies)
                    _instance = Simple.GetProxy(typeof(MySingleton));
                else
                    _instance = new MySingleton();
            }
            return _instance;
        }
    }
}

Note that the Simple class holds the "heavy lifting" of actually creating a proxy, intercepting and logging, etc. as well as the UseDynamicProxies flag so I can turn on/off proxy usage throughout the solution.