开发者

Decide class of object to be created from another assembly

开发者 https://www.devze.com 2023-03-27 20:42 出处:网络
I have a .net assembly that exposes a public class (named A) to be created other programs using reflection (Assembly.CreateInstance). For now, it works fine.

I have a .net assembly that exposes a public class (named A) to be created other programs using reflection (Assembly.CreateInstance). For now, it works fine.

But now I have two subclasses of A, say A1 and A2, and I need to create one or the other, depending on a runtime check. The client cannot be modified, it should believe that the object returned is of class A.

If I were using COM instead of .net, it would be easy enough: simply add the check into the IClassFactory.CreateInstance and be done. But is there a way to do this in .net?

Note: the obvious solution of using a proxy object, or similar, is not practical, because class A has several hundred methods (!) and I don't want to rer开发者_高级运维oute all of them.


Firstly, it should be noted that it would be easier if your client could use a factory method that you provide rather than having to hijack Activator.CreateInstance. Please consider that fully before reading on...

Here's an example using ContextBoundObject - it uses a counter as the "runtime check" to decide between B and C as the actual object, even though the caller asked for an A. Note that this also works if they used new A().

private static void Main()
{
    // subvert Activator.CreateInstance
    for(int i = 0 ; i < 100 ; i++)
    {
        object obj = Activator.CreateInstance(typeof (A));
        Console.WriteLine(obj.GetType().Name);
    }
    // subvert "new()"
    for(int i = 0 ; i < 100 ; i++)
    {
        object obj = new A();
        Console.WriteLine(obj.GetType().Name);
    }
}

class AProxyAttribute : ProxyAttribute
{
    int flipper;
    public override MarshalByRefObject CreateInstance(Type serverType)
    {
        if (serverType == typeof(A))
        {
            return ((flipper++)%2) == 0 ? (A) new B() : (A) new C();
        }
        return base.CreateInstance(serverType);
    }
}
[AProxy]
class A : ContextBoundObject { }
// the two subclasses
class B : A {}
class C : A{}

So yes, you can be dastardly and lie to the caller by giving them back something other than they asked for ;p This is fairly evil code, though. YMMV etc.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号