WCF反序列化有一些神奇之处.如何在不调用其构造函数的情况下实例化数据协定类型的实例?
例如,考虑这个数据合同:
[DataContract]
public sealed class CreateMe
{
[DataMember] private readonly string _name;
[DataMember] private readonly int _age;
private readonly bool _wasConstructorCalled;
public CreateMe()
{
_wasConstructorCalled = true;
}
// ... other members here
}
Run Code Online (Sandbox Code Playgroud)
通过DataContractSerializer
您获取此对象的实例时,您将看到该字段_wasConstructorCalled
是false
.
那么,WCF如何做到这一点?这是其他人可以使用的技术,还是隐藏在我们之外?
我正在努力提高应用程序的性能.我们有很多Activator.CreateInstance调用引起了一些悲伤.
我们基于一个接口(ITabDocument)实例化了很多类,在浏览后我想到了使用这段代码:
代码并不比使用我们拥有的Activator.CreateInstance代码更好(实际上稍慢).
public static Func<T> CreateInstance<T>(Type objType) where T : class, new()
{
var dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + objType.Name, objType, null, objType);
ILGenerator ilGen = dynMethod.GetILGenerator();
ilGen.Emit(OpCodes.Newobj, objType.GetConstructor(Type.EmptyTypes));
ilGen.Emit(OpCodes.Ret);
return (Func<T>)dynMethod.CreateDelegate(typeof(Func<T>));
}
Run Code Online (Sandbox Code Playgroud)
我想知道为什么会这样,我所做的只是:
ITabDocument document = CreateInstance<ITabDocument>(Type.GetType("[Company].Something"));
Run Code Online (Sandbox Code Playgroud)
是否有更好的方法来创建有助于上述内容的对象?当你不确定具体的类型时,它有点难.
在工作中阅读现有代码,我想知道这怎么可行.我有一个在程序集中定义的类:
[Serializable]
public class A
{
private readonly string _name;
private A(string name)
{
_name = name;
}
}
Run Code Online (Sandbox Code Playgroud)
在另一个集会中:
public void f(Type t) {
object o = Activator.CreateInstance(t);
}
Run Code Online (Sandbox Code Playgroud)
那个简单的电话 f(typeof(A))
我期望缺少无参数构造函数的例外,因为AFAIK,如果声明了ctor,编译器不应该生成默认的公共无参数构造函数.
此代码在.NET 2.0下运行.
[编辑]我很抱歉,但我误读了实际的代码...我提供的示例没有说明它.我接受了JonH的答案,因为它提供了一个很好的信息.
如果想要创建泛型的新实例,则需要定义新约束,如下所示:
public T SomeMethod<T>() where T : new()
{
return new T();
}
Run Code Online (Sandbox Code Playgroud)
是否可以使用反射在没有新约束的情况下创建T的实例,如此(包含伪代码):
public T SomeMethod<T>()
{
if (T has a default constructor)
{
return a new instance of T;
}
else
{
return Factory<T>.CreateNew();
}
}
Run Code Online (Sandbox Code Playgroud) 我和朋友正在测试使用编译表达式来创建对象,而不是Activator.CreateInstance<T>
遇到一些有趣的结果.我们发现当我们在每台机器上运行相同的代码时,我们看到完全相反的结果.他得到了预期的结果,在编译表达式中表现明显更好,而我惊讶地看到Activator.CreateInstance<T>
表现为2x.
两台计算机都运行在.NET 4.0中编译
计算机1安装了.NET 4.5.电脑2没有.
计算机1超过100000个对象:
45ms - Type<Test>.New()
19ms - System.Activator.CreateInstance<Test>();
Run Code Online (Sandbox Code Playgroud)
计算机2超过100000个对象:
13ms - Type<Test>.New()
86ms - System.Activator.CreateInstance<Test>();
Run Code Online (Sandbox Code Playgroud)
以下是代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
namespace NewNew
{
class Program
{
static void Main(string[] args)
{
Stopwatch benchmark = Stopwatch.StartNew();
for (int i = 0; i < 100000; i++)
{
var result = Type<Test>.New();
}
benchmark.Stop();
Console.WriteLine(benchmark.ElapsedMilliseconds + " Type<Test>.New()");
benchmark = Stopwatch.StartNew();
for (int i = 0; i < 100000; …
Run Code Online (Sandbox Code Playgroud) 我开始阅读关于反射的内容,我想知道有没有办法在程序运行时创建构造函数。例如:获取类 C 并检查 C 是否有空构造函数,如果没有,则创建并使用它来创建此实例。构造函数也可能有参数。
我怎样才能做到这一点?谢谢
我正在为别人的代码编写单元测试,我不允许修改.
说我有:
class BadClass
{
public BadClass()
{
// the service isn't going to be running during testing
// it also has no interface
someFlag = AGloballyStoredService.getSomeFlag();
}
public bool someFlag;
}
Run Code Online (Sandbox Code Playgroud)
用于:
class AnotherBadClass
{
public AnotherBadClass(BadClass badClass)
{
someFlag = badClass.someFlag;
}
public bool someFlag;
}
Run Code Online (Sandbox Code Playgroud)
说我想要测试:
public void AnotherBadClassConstructorTest()
{
BadClass badClass = new BadClass();
AnotherBadClass anotherBadClass = new AnotherBadClass(badClass);
Assert.IsNotNull(anotherBadClass);
}
Run Code Online (Sandbox Code Playgroud)
我想模拟BadClass,但它没有接口,如果服务没有运行,它在构造函数中失败.
考虑到我无法修改我正在测试的代码,是否有一种直接的方法来使其工作?
如果归结为它,我可以告诉他们,他们必须让我修改现有的代码库或接受该模块的10%以下的覆盖率.
我想知道为什么一个class
不能serialization
没有空构造函数。
当我收到此错误消息时,我尝试了几次:
ClassName cannot be serialized because it does not have a parameterless constructor.
Run Code Online (Sandbox Code Playgroud)
代码是这样的:
public void DoSerialize(string path)
{
try
{
XmlSerializer serializer = new XmlSerializer(typeof(List<MyClass>));
TextWriter textWriter = new StreamWriter(path);
serializer.Serialize(textWriter, MyList);
textWriter.Close();
}
catch (Exception e)
{
}
}
Run Code Online (Sandbox Code Playgroud)
真的,当我添加一个空的构造函数时,它起作用了