使用 Activator.CreateInstance 时设置仅初始化属性
Setting init-only properties when using Activator.CreateInstance
C# 9.0 引入了 init-only class 属性功能,但在通过 class 类型和 Activator.CreateInstance 创建实例时不能使用它们。一个简单的例子:
class Person
{
public string Name { get; init; }
}
void Test()
{
Person person = (Person)Activator.CreateInstance(typeof(Person));
person.Name = "Bob"; // Doesn't work
}
寻找除了使用构造函数参数(太多)之外的其他解决方案。
Init 应该在对象的构造中初始化,因此您应该在构造函数中初始化它的值。你可以这样做:
(Person)Activator.CreateInstance(typeof(Person), "Bob");
注意,需要添加合适的构造函数。
class Person
{
public Person(string name)
{
Name = name;
}
public string Name { get; init; }
}
Init 属性只能在以下 contexts:
中设置
- 在对象初始化期间
- 在
with
表达式初始化程序期间
- 在包含或派生类型的实例构造函数内,在
this
或 base
- 在任何 属性 的
init
访问器内,在 this
或 base
- 带命名参数的内部属性用法
反过来,对象初始化只是语法糖,无需直接调用构造函数即可设置实例属性或字段,本质上是从
Person person = new Person { Name = "Bob" };
至
Person person2 = new Person();
person2.Name = "test";
Person person = person;
当使用 Activator.CreateInstance
时,您绕过了这个语法糖。也就是说,如果您已经在使用 Activator.CreateInstance
,您可能会很乐意接受额外的反射命中。您可以简单地调用 PropertyInfo.SetValue
在对象创建后设置值:
Person person = (Person)Activator.CreateInstance(typeof(Person));
person.GetType().GetProperty("Name").SetValue(person, "Bob");
或者,您可以创建构造函数并将值传递给构造函数。
C# 9.0 引入了 init-only class 属性功能,但在通过 class 类型和 Activator.CreateInstance 创建实例时不能使用它们。一个简单的例子:
class Person
{
public string Name { get; init; }
}
void Test()
{
Person person = (Person)Activator.CreateInstance(typeof(Person));
person.Name = "Bob"; // Doesn't work
}
寻找除了使用构造函数参数(太多)之外的其他解决方案。
Init 应该在对象的构造中初始化,因此您应该在构造函数中初始化它的值。你可以这样做:
(Person)Activator.CreateInstance(typeof(Person), "Bob");
注意,需要添加合适的构造函数。
class Person
{
public Person(string name)
{
Name = name;
}
public string Name { get; init; }
}
Init 属性只能在以下 contexts:
中设置- 在对象初始化期间
- 在
with
表达式初始化程序期间 - 在包含或派生类型的实例构造函数内,在
this
或base
- 在任何 属性 的
init
访问器内,在this
或base
- 带命名参数的内部属性用法
反过来,对象初始化只是语法糖,无需直接调用构造函数即可设置实例属性或字段,本质上是从
Person person = new Person { Name = "Bob" };
至
Person person2 = new Person();
person2.Name = "test";
Person person = person;
当使用 Activator.CreateInstance
时,您绕过了这个语法糖。也就是说,如果您已经在使用 Activator.CreateInstance
,您可能会很乐意接受额外的反射命中。您可以简单地调用 PropertyInfo.SetValue
在对象创建后设置值:
Person person = (Person)Activator.CreateInstance(typeof(Person));
person.GetType().GetProperty("Name").SetValue(person, "Bob");
或者,您可以创建构造函数并将值传递给构造函数。