使用内部构造函数实例化一个类

我有一个类的构造函数被定义为内部的,这意味着我不能实例化它。 虽然这可能是有道理的,但我仍然希望做一次debugging和研究的目的。

reflection可以这样做吗? 我知道我可以访问私人/内部成员,但我可以调用内部构造函数吗?

或者,因为构造函数没有什么重要,我可以使用reflection来说“看,只给我一个类的实例,而不调用构造函数,我会做手动工作”?

性能和“稳定性”在这里不是问题,因为它不是生产代码。

编辑:就像澄清:可悲的是,我不控制其他程序集,没有它的源代码,我只是试图了解它是如何工作的,因为它是文件旁边不存在,但我应该与它。

FormatterServices.GetUninitializedObject方法存在(命名空间:System.Runtime.Serialization),它应该不会调用构造函数,如果你真的想尝试这种方法。

另一种方法是提名召集大会作为“朋友”大会。

只需将其添加到包含内部构造函数的程序集的AssemblyInfo.cs文件中:

[assembly: InternalsVisibleTo("Calling.Assembly")] 

如果您无权访问程序集,则也可以直接调用构造函数(使用Reflection):

 MyClass obj = (MyClass) typeof(MyClass).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null).Invoke(null); 

这是从这个答案派生的方法:

 public static T CreateInstance<T>(params object[] args) { var type = typeof (T); var instance = type.Assembly.CreateInstance( type.FullName, false, BindingFlags.Instance | BindingFlags.NonPublic, null, args, null, null); return (T) instance; } 

示例用法(这是我需要为unit testing创​​build的Kinect SDKtypes):

 DiscreteGestureResult a = CreateInstance<DiscreteGestureResult>(false, false, 0.5f); 

我经历了同样的情况,并创build了一个名为“InternalsVisibleToInjector”的小工具。 它使用ILDASM和ILASM来反汇编,修改和重新汇编和汇编,并将我select的程序集名称添加到目标程序集的InternalsVisibleTo列表中。 它在我的情况下工作得很好。

我已经发布了这个工具的源代码(VS 2008 C#WinForm):

downloads/InternalsVisibleToInjector.zip

如果程序集签名,这可能不起作用。 请采取一切适当的预防措施(即在使用前备份assembly,并确保您的法律依据稳固)

如果有人再次绊倒,这里是一个如何通过反思来提高它的例子:

 var args = FormatterServices.GetUninitializedObject(typeof(SizeChangedEventArgs)) as SizeChangedEventArgs; Debug.Assert(args != null); var field = typeof(SizeChangedEventArgs).GetField("_previousSize", BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(field != null); field.SetValue(args, new Size(0,0)); field = typeof(SizeChangedEventArgs).GetField("_element", BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(field != null); field.SetValue(args, GraphicsWrapper); field = typeof(RoutedEventArgs).GetField("_source", BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(field != null); field.SetValue(args, GraphicsWrapper); field = typeof(RoutedEventArgs).GetField("_routedEvent", BindingFlags.Instance | BindingFlags.NonPublic); Debug.Assert(field != null); field.SetValue(args, SizeChangedEvent); GraphicsWrapper.RaiseEvent(args); 

GraphicsWrapper是你想要从中提取的WPF控件。

如果你想避免reflection,你可以使用expression式。 这是一个使用string值调用私有构造函数的示例。

  private static Func<string, T> CreateInstanceFunc() { var flags = BindingFlags.NonPublic | BindingFlags.Instance; var ctor = typeof(T).GetConstructors(flags).Single( ctors => { var parameters = ctors.GetParameters(); return parameters.Length == 1 && parameters[0].ParameterType == typeof(string); }); var value = Expression.Parameter(typeof(string), "value"); var body = Expression.New(ctor, value); var lambda = Expression.Lambda<Func<string, T>>(body, value); return lambda.Compile(); } 

internal并不意味着你不能实例化它。 这只是意味着只有来自同一个议会的成员可能会这样称呼它。

出于testing目的,您可以使用InternalsVisibleTo属性允许testing程序集访问内部。 请参阅http://msdn.microsoft.com/zh-CN/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

你可以使用reflection器来分析它的源代码,并从这个数字出来的内部工作。