C# 用测试数据填充一个类
我使用反射用测试数据填充给定的C#类C# 用测试数据填充一个类,c#,unit-testing,reflection,C#,Unit Testing,Reflection,我使用反射用测试数据填充给定的C#类 public object CreateObj(Type type) { var obj = Activator.CreateInstance(type); var fields = type.GetFields(); foreach (var field in fields) { field.SetValue(obj, GetRnd(field.FieldType)); } return o
public object CreateObj(Type type)
{
var obj = Activator.CreateInstance(type);
var fields = type.GetFields();
foreach (var field in fields)
{
field.SetValue(obj, GetRnd(field.FieldType));
}
return obj;
}
GetRnd()
函数根据字段类型设置值:
private object GetRnd(Type type)
{
if (type == typeof(int))
{
return 4;
}
else if (type == typeof(string))
{
return "text";
}
else
{
throw new Exception();
}
}
只要我传递给CreateObj()
一个合适的类,这就可以工作。我想让它甚至可以与基本类型(字符串、int等)一起工作
现在,当我传递一个简单的“int”时,我得到了一个“SetType():无法设置常量字段”异常。检查该类型是否为值“type.IsValue”,这意味着类型传入参数是标量类型。您没有问问题,但我想您想知道: 如何将此代码更改为设置常量或只读字段 你不能。它们是只读的 我怎样才能让它与
int
和其他类型一起工作
您可以通过检查只读字段或常量字段来防止错误:
foreach (var field in fields)
{
if (!(field.IsInitOnly || field.IsLiteral))
field.SetValue(obj, GetRnd(field.FieldType));
}
我可以使用这个类生成一个随机整数或字符串吗
不是通过改变它的字段。像int
和string
这样的基本类型是不可变的。“更改”变量值的唯一方法是用新值覆盖它。因此,您需要处理不可变类型的情况:
static Random rand = new Random();
public object CreateObj(Type type)
{
if(type == typeof(int)) return GetRnd(type);
if(type == typeof(string)) return GetRnd(type);
var obj = Activator.CreateInstance(type);
var fields = type.GetFields();
foreach (var field in fields)
{
field.SetValue(obj, GetRnd(field.FieldType));
}
return obj;
}
还有什么可以改进的
- 它只设置字段,不设置属性。如果您有一个具有包装私有字段的属性的类,则不会设置它们
- 它不适用于没有公共无参数构造函数的类型
class RandomObjectFactory
{
// creates an object of type T that has a default constructor
public T CreateObject<T>() where T: class, new()
{
...
创建对象的代码如下:
public T CreateObject<T>() where T: class, new()
{
var obj = Activator.CreateInstance<T>();
foreach (var property in typeof(T).GetProperties()
.Where(property => property.CanWrite))
{
if (property.PropertyType.IsPrimitive)
{
property.SetValue(obj, this.CreatePrimitive
(Type.GetTypeCode(property.PropertyType)));
}
else if (property.PropertyType.IsClass)
{
property.SetValue(obj, this.CreatObject...
发明类似的东西来创建结构或数组。看一看。它可以提供随机测试数据和更多。(不是我的反对票,事实上这是一个有效的问题)@SriramSakthivel-AutoFixture很棒,经常使用它。谢谢。我会用的。就为了它,对于上述问题,什么样的解决方案才是好的呢?我想说的是AutoFac。它是专门为解决这个问题而设计的。它是开源的,你也可以从nuget下载。如果您想自己解决这个问题,那么您将编写大量的代码,但没有回报;)基本上AutoFixture是做什么的。如果我问“如何做”某件事,请不要回答“你应该做这个而不是那个”。我不是在要求一个更好的解决方案(它总是存在的),而是如何在给定的环境和给定的垃圾上解决眼前的问题。标记为Stackoverglow帮助中心的不当摘录-我们的模型:粗鲁和轻视语言是不好的。你的语气应该与你与你尊敬的人以及你想尊敬的人交谈的方式相匹配。如果你没有时间礼貌地说些什么,就留给有礼貌的人吧;
public T CreatePrimitive<T> where T: struct, IConvertible
{
...
int i = Create(typeof(Form));
public T CreateObject<T>() where T: class, new()
{
var obj = Activator.CreateInstance<T>();
foreach (var property in typeof(T).GetProperties()
.Where(property => property.CanWrite))
{
if (property.PropertyType.IsPrimitive)
{
property.SetValue(obj, this.CreatePrimitive
(Type.GetTypeCode(property.PropertyType)));
}
else if (property.PropertyType.IsClass)
{
property.SetValue(obj, this.CreatObject...
private object CreateObject(Type type)
{
var obj = Activator.CreateInstance(type);
foreach (var property in typeof(T).GetProperties()
.Where(property => property.CanWrite))
{
if (property.PropertyType.IsPrimitive)
{
property.SetValue(obj, this.CreatePrimitive
(Type.GetTypeCode(property.PropertyType)));
}
else if (property.PropertyType.IsClass)
{
property.SetValue(obj, this.CreateObject (property.PropertyType);
}
}
return obj;
}
private object CreatePrimitive(TypeCode typeCode)
{
switch (typeCode)
{
case TypeCode:Boolean:
return this.rnd.Next(2) == 0;
case TypeCode.Byte:
return (Byte)this.rnd.Next(Byte.MinValue, Byte.MaxValue);
case TypeCode.DateTime:
long ticks = (long)((DateTime.MaxValue.Ticks - DateTime.MinValue.Ticks) * rnd.NextDouble() + DateTime.MinValue.Ticks);
return new DateTime(ticks);
// etc.
}
return obj;
}