C# 如何从类型创建新的对象实例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/752/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create a new object instance from a Type
提问by tags2k
One may not always know the Type
of an object at compile-time, but may need to create an instance of the Type
.
Type
在编译时可能并不总是知道对象的 ,但可能需要创建Type
.
How do you get a new object instance from a Type
?
你如何从 a 中获取一个新的对象实例Type
?
采纳答案by Karl Seguin
The Activator
class within the root System
namespace is pretty powerful.
Activator
根System
命名空间中的类非常强大。
There are a lot of overloads for passing parameters to the constructor and such. Check out the documentation at:
有很多用于将参数传递给构造函数等的重载。查看文档:
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
or (new path)
或(新路径)
https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance
https://docs.microsoft.com/en-us/dotnet/api/system.activator.createinstance
Here are some simple examples:
下面是一些简单的例子:
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");
回答by tags2k
One implementation of this problem is to attempt to call the parameter-less constructor of the Type:
此问题的一种实现是尝试调用 Type 的无参数构造函数:
public static object GetNewObject(Type t)
{
try
{
return t.GetConstructor(new Type[] { }).Invoke(new object[] { });
}
catch
{
return null;
}
}
Here is the same approach, contained in a generic method:
这是相同的方法,包含在通用方法中:
public static T GetNewObject<T>()
{
try
{
return (T)typeof(T).GetConstructor(new Type[] { }).Invoke(new object[] { });
}
catch
{
return default(T);
}
}
回答by Tom Mayfield
If this is for something that will be called a lot in an application instance, it's a lot faster to compile and cache dynamic code instead of using the activator or ConstructorInfo.Invoke()
. Two easy options for dynamic compilation are compiled Linq Expressionsor some simple IL
opcodes and DynamicMethod
. Either way, the difference is huge when you start getting into tight loops or multiple calls.
如果这是为了在应用程序实例中被大量调用的东西,编译和缓存动态代码比使用激活器或ConstructorInfo.Invoke()
. 动态编译的两个简单选项是编译的Linq 表达式或一些简单的IL
操作码和DynamicMethod
. 无论哪种方式,当您开始进入紧密循环或多次调用时,差异都是巨大的。
回答by Konrad Rudolph
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
The Activator
class has a generic variant that makes this a bit easier:
该Activator
班有一个通用的变种,使这是一个更容易一些:
ObjectType instance = Activator.CreateInstance<ObjectType>();
回答by Brady Moritz
Wouldn't the generic T t = new T();
work?
通用T t = new T();
不行吗?
回答by vikram nayak
public AbstractType New
{
get
{
return (AbstractType) Activator.CreateInstance(GetType());
}
}
回答by BSharp
If you want to use the default constructor then the solution using System.Activator
presented earlier is probably the most convenient. However, if the type lacks a default constructor or you have to use a non-default one, then an option is to use reflection or System.ComponentModel.TypeDescriptor
. In case of reflection, it is enough to know just the type name (with its namespace).
如果您想使用默认构造函数,那么使用System.Activator
前面介绍的解决方案可能是最方便的。但是,如果该类型缺少默认构造函数或者您必须使用非默认构造函数,则可以选择使用反射或System.ComponentModel.TypeDescriptor
. 在反射的情况下,只知道类型名称(及其命名空间)就足够了。
Example using reflection:
使用反射的示例:
ObjectType instance =
(ObjectType)System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(
typeName: objectType.FulName, // string including namespace of the type
ignoreCase: false,
bindingAttr: BindingFlags.Default,
binder: null, // use default binder
args: new object[] { args, to, constructor },
culture: null, // use CultureInfo from current thread
activationAttributes: null
);
Example using TypeDescriptor
:
使用示例TypeDescriptor
:
ObjectType instance =
(ObjectType)System.ComponentModel.TypeDescriptor.CreateInstance(
provider: null, // use standard type description provider, which uses reflection
objectType: objectType,
argTypes: new Type[] { types, of, args },
args: new object[] { args, to, constructor }
);
回答by Sarath Avanavu
Its pretty simple. Assume that your classname is Car
and the namespace is Vehicles
, then pass the parameter as Vehicles.Car
which returns object of type Car
. Like this you can create any instance of any class dynamically.
它很简单。假设您的类名是Car
,命名空间是Vehicles
,然后传递参数 asVehicles.Car
返回类型的对象Car
。像这样,您可以动态创建任何类的任何实例。
public object GetInstance(string strNamesapace)
{
Type t = Type.GetType(strNamesapace);
return Activator.CreateInstance(t);
}
If your Fully Qualified Name(ie, Vehicles.Car
in this case) is in another assembly, the Type.GetType
will be null. In such cases, you have loop through all assemblies and find the Type
. For that you can use the below code
如果您的完全限定名称(即,Vehicles.Car
在这种情况下)在另一个程序集中,Type.GetType
则将为空。在这种情况下,您可以遍历所有程序集并找到Type
. 为此,您可以使用以下代码
public object GetInstance(string strFullyQualifiedName)
{
Type type = Type.GetType(strFullyQualifiedName);
if (type != null)
return Activator.CreateInstance(type);
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
{
type = asm.GetType(strFullyQualifiedName);
if (type != null)
return Activator.CreateInstance(type);
}
return null;
}
And you can get the instance by calling the above method.
并且可以通过调用上面的方法来获取实例。
object objClassInstance = GetInstance("Vehicles.Car");
回答by Darrel Lee
I can across this question because I was looking to implement a simple CloneObject method for arbitrary class (with a default constructor)
我可以解决这个问题,因为我希望为任意类实现一个简单的 CloneObject 方法(使用默认构造函数)
With generic method you can require that the type implements New().
使用泛型方法,您可以要求该类型实现 New()。
Public Function CloneObject(Of T As New)(ByVal src As T) As T
Dim result As T = Nothing
Dim cloneable = TryCast(src, ICloneable)
If cloneable IsNot Nothing Then
result = cloneable.Clone()
Else
result = New T
CopySimpleProperties(src, result, Nothing, "clone")
End If
Return result
End Function
With non-generic assume the type has a default constructor and catch an exception if it doesn't.
对于非泛型,假设该类型具有默认构造函数,如果没有,则捕获异常。
Public Function CloneObject(ByVal src As Object) As Object
Dim result As Object = Nothing
Dim cloneable As ICloneable
Try
cloneable = TryCast(src, ICloneable)
If cloneable IsNot Nothing Then
result = cloneable.Clone()
Else
result = Activator.CreateInstance(src.GetType())
CopySimpleProperties(src, result, Nothing, "clone")
End If
Catch ex As Exception
Trace.WriteLine("!!! CloneObject(): " & ex.Message)
End Try
Return result
End Function
回答by Serj-Tm
Compiled expression is best way! (for performance to repeatedly create instance in runtime).
编译表达式是最好的方法!(为了在运行时重复创建实例的性能)。
static readonly Func<X> YCreator = Expression.Lambda<Func<X>>(
Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes))
).Compile();
X x = YCreator();
Statistics (2012):
统计数据(2012):
Iterations: 5000000
00:00:00.8481762, Activator.CreateInstance(string, string)
00:00:00.8416930, Activator.CreateInstance(type)
00:00:06.6236752, ConstructorInfo.Invoke
00:00:00.1776255, Compiled expression
00:00:00.0462197, new
Statistics (2015, .net 4.5, x64):
统计数据(2015 年,.net 4.5,x64):
Iterations: 5000000
00:00:00.2659981, Activator.CreateInstance(string, string)
00:00:00.2603770, Activator.CreateInstance(type)
00:00:00.7478936, ConstructorInfo.Invoke
00:00:00.0700757, Compiled expression
00:00:00.0286710, new
Statistics (2015, .net 4.5, x86):
统计数据(2015 年,.net 4.5,x86):
Iterations: 5000000
00:00:00.3541501, Activator.CreateInstance(string, string)
00:00:00.3686861, Activator.CreateInstance(type)
00:00:00.9492354, ConstructorInfo.Invoke
00:00:00.0719072, Compiled expression
00:00:00.0229387, new
Statistics (2017, LINQPad 5.22.02/x64/.NET 4.6):
统计数据(2017 年,LINQPad 5.22.02/x64/.NET 4.6):
Iterations: 5000000
No args
00:00:00.3897563, Activator.CreateInstance(string assemblyName, string typeName)
00:00:00.3500748, Activator.CreateInstance(Type type)
00:00:01.0100714, ConstructorInfo.Invoke
00:00:00.1375767, Compiled expression
00:00:00.1337920, Compiled expression (type)
00:00:00.0593664, new
Single arg
00:00:03.9300630, Activator.CreateInstance(Type type)
00:00:01.3881770, ConstructorInfo.Invoke
00:00:00.1425534, Compiled expression
00:00:00.0717409, new
Statistics (2019, x64/.NET 4.8):
统计数据(2019,x64/.NET 4.8):
Iterations: 5000000
No args
00:00:00.3287835, Activator.CreateInstance(string assemblyName, string typeName)
00:00:00.3122015, Activator.CreateInstance(Type type)
00:00:00.8035712, ConstructorInfo.Invoke
00:00:00.0692854, Compiled expression
00:00:00.0662223, Compiled expression (type)
00:00:00.0337862, new
Single arg
00:00:03.8081959, Activator.CreateInstance(Type type)
00:00:01.2507642, ConstructorInfo.Invoke
00:00:00.0671756, Compiled expression
00:00:00.0301489, new
Statistics (2019, x64/.NET Core 3.0):
统计数据(2019,x64/.NET Core 3.0):
Iterations: 5000000
No args
00:00:00.3226895, Activator.CreateInstance(string assemblyName, string typeName)
00:00:00.2786803, Activator.CreateInstance(Type type)
00:00:00.6183554, ConstructorInfo.Invoke
00:00:00.0483217, Compiled expression
00:00:00.0485119, Compiled expression (type)
00:00:00.0434534, new
Single arg
00:00:03.4389401, Activator.CreateInstance(Type type)
00:00:01.0803609, ConstructorInfo.Invoke
00:00:00.0554756, Compiled expression
00:00:00.0462232, new
Full code:
完整代码:
static X CreateY_New()
{
return new Y();
}
static X CreateY_New_Arg(int z)
{
return new Y(z);
}
static X CreateY_CreateInstance()
{
return (X)Activator.CreateInstance(typeof(Y));
}
static X CreateY_CreateInstance_String()
{
return (X)Activator.CreateInstance("Program", "Y").Unwrap();
}
static X CreateY_CreateInstance_Arg(int z)
{
return (X)Activator.CreateInstance(typeof(Y), new object[] { z, });
}
private static readonly System.Reflection.ConstructorInfo YConstructor =
typeof(Y).GetConstructor(Type.EmptyTypes);
private static readonly object[] Empty = new object[] { };
static X CreateY_Invoke()
{
return (X)YConstructor.Invoke(Empty);
}
private static readonly System.Reflection.ConstructorInfo YConstructor_Arg =
typeof(Y).GetConstructor(new[] { typeof(int), });
static X CreateY_Invoke_Arg(int z)
{
return (X)YConstructor_Arg.Invoke(new object[] { z, });
}
private static readonly Func<X> YCreator = Expression.Lambda<Func<X>>(
Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes))
).Compile();
static X CreateY_CompiledExpression()
{
return YCreator();
}
private static readonly Func<X> YCreator_Type = Expression.Lambda<Func<X>>(
Expression.New(typeof(Y))
).Compile();
static X CreateY_CompiledExpression_Type()
{
return YCreator_Type();
}
private static readonly ParameterExpression YCreator_Arg_Param = Expression.Parameter(typeof(int), "z");
private static readonly Func<int, X> YCreator_Arg = Expression.Lambda<Func<int, X>>(
Expression.New(typeof(Y).GetConstructor(new[] { typeof(int), }), new[] { YCreator_Arg_Param, }),
YCreator_Arg_Param
).Compile();
static X CreateY_CompiledExpression_Arg(int z)
{
return YCreator_Arg(z);
}
static void Main(string[] args)
{
const int iterations = 5000000;
Console.WriteLine("Iterations: {0}", iterations);
Console.WriteLine("No args");
foreach (var creatorInfo in new[]
{
new {Name = "Activator.CreateInstance(string assemblyName, string typeName)", Creator = (Func<X>)CreateY_CreateInstance},
new {Name = "Activator.CreateInstance(Type type)", Creator = (Func<X>)CreateY_CreateInstance},
new {Name = "ConstructorInfo.Invoke", Creator = (Func<X>)CreateY_Invoke},
new {Name = "Compiled expression", Creator = (Func<X>)CreateY_CompiledExpression},
new {Name = "Compiled expression (type)", Creator = (Func<X>)CreateY_CompiledExpression_Type},
new {Name = "new", Creator = (Func<X>)CreateY_New},
})
{
var creator = creatorInfo.Creator;
var sum = 0;
for (var i = 0; i < 1000; i++)
sum += creator().Z;
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < iterations; ++i)
{
var x = creator();
sum += x.Z;
}
stopwatch.Stop();
Console.WriteLine("{0}, {1}", stopwatch.Elapsed, creatorInfo.Name);
}
Console.WriteLine("Single arg");
foreach (var creatorInfo in new[]
{
new {Name = "Activator.CreateInstance(Type type)", Creator = (Func<int, X>)CreateY_CreateInstance_Arg},
new {Name = "ConstructorInfo.Invoke", Creator = (Func<int, X>)CreateY_Invoke_Arg},
new {Name = "Compiled expression", Creator = (Func<int, X>)CreateY_CompiledExpression_Arg},
new {Name = "new", Creator = (Func<int, X>)CreateY_New_Arg},
})
{
var creator = creatorInfo.Creator;
var sum = 0;
for (var i = 0; i < 1000; i++)
sum += creator(i).Z;
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < iterations; ++i)
{
var x = creator(i);
sum += x.Z;
}
stopwatch.Stop();
Console.WriteLine("{0}, {1}", stopwatch.Elapsed, creatorInfo.Name);
}
}
public class X
{
public X() { }
public X(int z) { this.Z = z; }
public int Z;
}
public class Y : X
{
public Y() {}
public Y(int z) : base(z) {}
}