유형에서 새 개체 인스턴스를 만드는 방법
사람은 항상 알지 못할 수도 있습니다.Type
컴파일 시간에 객체의. 그러나 인스턴스를 만들어야 할 수 있습니다.Type
.
에서 새 개체 인스턴스를 가져오려면 어떻게 해야 합니까?Type
?
그Activator
근저에 있는 계급System
네임스페이스는 매우 강력합니다.
생성자에게 매개 변수를 전달하는 등의 작업에는 많은 오버로드가 있습니다.다음 위치에서 설명서를 확인하십시오.
http://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx
또는 (새 경로)
https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance
다음은 몇 가지 간단한 예입니다.
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
ObjectType instance = (ObjectType)Activator.CreateInstance("MyAssembly","MyNamespace.ObjectType");
답변은 이미 제공되었습니다.
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
하지만, 그Activator
클래스는 매개 변수가 없는 생성자에 대한 일반적인 변형을 가지고 있으며, 이는 캐스트를 불필요하게 만들고 객체의 런타임 유형을 전달할 필요가 없게 함으로써 약간 더 읽기 쉽게 만듭니다.
ObjectType instance = Activator.CreateInstance<ObjectType>();
컴파일된 식을 사용하는 것이 가장 좋습니다!(실행 시간에 인스턴스를 반복적으로 만드는 성능을 위해).
static readonly Func<X> YCreator = Expression.Lambda<Func<X>>(
Expression.New(typeof(Y).GetConstructor(Type.EmptyTypes))
).Compile();
X x = YCreator();
통계(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
통계(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
통계(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
통계(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
통계(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
통계(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
전체 코드:
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) {}
}
꽤 간단합니다.클래스 이름이 다음과 같다고 가정합니다.Car
그리고 네임스페이스는Vehicles
그런 다음 매개 변수를 다음과 같이 전달합니다.Vehicles.Car
유형의 개체를 반환합니다.Car
이와 같이 모든 클래스의 인스턴스를 동적으로 만들 수 있습니다.
public object GetInstance(string strNamesapace)
{
Type t = Type.GetType(strNamesapace);
return Activator.CreateInstance(t);
}
정규화된 이름(즉,Vehicles.Car
이 경우)는 다른 어셈블리에 있습니다.Type.GetType
null이 됩니다.이러한 경우, 모든 어셈블리를 루프하고 다음을 찾습니다.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;
}
그리고 위의 방법을 호출하면 인스턴스를 얻을 수 있습니다.
object objClassInstance = GetInstance("Vehicles.Car");
반사를 사용하지 않는 경우:
private T Create<T>() where T : class, new()
{
return new T();
}
만약 이것이 응용 프로그램 인스턴스에서 많이 호출될 어떤 것에 대한 것이라면, 활성화 프로그램을 사용하는 대신 동적 코드를 컴파일하고 캐시하는 것이 훨씬 빠릅니다.ConstructorInfo.Invoke()
동적 컴파일을 위한 두 가지 쉬운 옵션은 Linq Expressions 또는 몇 가지 간단한 opcode입니다. 어느 쪽이든, 여러분이 타이트 루프나 여러 개의 통화를 시작할 때, 그 차이는 큽니다.
기본 생성자를 사용하려면 다음을 사용합니다.System.Activator
아마도 앞에서 제시한 것이 가장 편리할 것입니다.해야 하는 또는 "" "" "" "" "" "" "" ""를 사용하는 .System.ComponentModel.TypeDescriptor
반영의 경우 네임스페이스와 함께 형식 이름만 알면 됩니다.
반사를 사용한 예:
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
);
를 한 예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 }
);
이 문제를 고려할 때 활성화기는 매개 변수가 없는 CT가 있을 때 작동합니다.이것이 제약 조건이라면 사용을 고려해 보십시오.
System.Runtime.Serialization.FormatterServices.GetSafeUninitializedObject()
은▁thet▁wouldn'.T t = new T();
일?
public AbstractType New
{
get
{
return (AbstractType) Activator.CreateInstance(GetType());
}
}
(기본 생성자를 사용하여) 임의 클래스에 대한 간단한 CloneObject 메서드를 구현하려고 했기 때문에 이 질문을 이해할 수 있습니다.
일반적인 방법을 사용하면 유형이 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
일반이 아닌 경우 형식에 기본 생성자가 있다고 가정하고 그렇지 않은 경우 예외를 탐지합니다.
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
언급URL : https://stackoverflow.com/questions/752/how-to-create-a-new-object-instance-from-a-type
'programing' 카테고리의 다른 글
ASP.NET MVC 사용자 지정 오류 처리 Application_ErrorGlobal.asax? (0) | 2023.05.29 |
---|---|
부울을 사용하는 이유.ToString 출력 "참"이 아닌 "참" (0) | 2023.05.24 |
데이터 주석이 있는 DateTime 형식을 할당하시겠습니까? (0) | 2023.05.24 |
Angular에서 컨트롤이 생성된 후 FormControl에 Validator를 추가하는 방법은 무엇입니까? (0) | 2023.05.24 |
Git에서 되돌린 병합 다시 수행 (0) | 2023.05.24 |