这是一个bug吗?使用private访问修饰符构造函数的Activator.CreateInstance?

3

所以我有这个单例模式的代码

public class Foo
{
    private static Foo instance;
    private Foo() { }
    public static Foo Instance
         {
             get
             {
                 if (instance == null) instance = Activator.CreateInstance<Foo>();
                    return instance;
             }
         }
}

这并不起作用,因为Foo的构造函数设置为私有(抛出异常,找不到该类的无参数构造函数)。

当然,传统的new Foo()在那里可以工作。我知道Activator由于访问限制无法访问Foo的私有构造函数,但是我认为每个对象实例化都是由Activator完成的:那么在这种情况下,为什么Activator不起作用呢?

谢谢!


你可能是指在“实例化是由Activator完成”的情况下,CreateInstance 的不同重载吧? - Alexei Levenkov
为什么?new Foo() 更短。 - user1064248
@wonko79 学术问题。此外,有很多时候你被迫使用 Activator.CreateInstance,我想知道。 - Gaspa79
2个回答

4

这并不是 Activator 的局限性,而只是你选择的 CreateInstance 方法版本的限制。将其更改为版本 CreateInstance(Type type, bool nonPublic),它就会运行:

if (instance == null) instance = (Foo)Activator.CreateInstance(typeof(Foo), true);

以下是来自MSDN关于此方法的说明:

从.NET Framework 2.0 Service Pack 1开始,如果调用方已被授予带有ReflectionPermissionFlag.RestrictedMemberAccess标志的反射权限,并且包含非公共类型和成员的程序集的授予集已经被限制为调用方的授予集或其子集,则可以使用此方法访问非公共类型和成员。 (请参见Reflection的安全注意事项。) 要使用此功能,您的应用程序应针对.NET Framework 3.5或更高版本。


4

Activator 只接受 public 构造函数。如果您需要使用其他构造函数,请以不同的方式调用:

(Foo)Activator.CreateInstance(typeof(Foo), nonPublic:true);

不幸的是,通用版本并没有提供任何额外的选项...这意味着你会得到一些拆箱。然而,你也在进行反射,这已经很慢了...所以我猜这更多地是学术性的,而不是关注性能。


哦,非公共的:真不错。通用版本没有那个。谢谢! - Gaspa79
@Andrew,不会的,通用版本在内部进行了强制转换。 - Konrad Kokosa
@KonradKokosa,您不需要手动将CreateInstance方法的新实例强制转换为通用版本,因为它已经被类型化了。我想他是这个意思。 - Gaspa79
1
@KonradKokosa 我更多地是指失去了通用版本的“优雅”。我认为在反射方面,强制转换可能是整个操作中最快的部分。 - poy
@Andrew,如果从“优雅”的角度来说,你当然是正确的。没有人知道为什么没有带有nonPublic标志的通用版本。但是你的评论是误导性的——听起来通用版本没有进行拆箱/转换。 - Konrad Kokosa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接