예제와 함께 Activator.CreateInstance의 목적?


124

누군가 Activator.CreateInstance()목적을 자세히 설명 할 수 있습니까 ?


6
아마도 일반적인 오버로드에서 더 큰 문서와 예제를 사용할 수 없습니다. 의 문서 CreateInstance(Type type)CreateInstance<T>()과부하 와 일치 하는 것이 좋습니다 .
Claus Jørgensen

4
MSDN 페이지에는 "로컬 또는 원격으로 개체 유형을 만들거나 기존 원격 개체에 대한 참조를 가져 오는 메서드가 포함되어 있습니다.이 클래스는 상속 될 수 없습니다."라는 단일 설명 줄만 있습니다. msdn.microsoft.com/en-us/library/system.activator.aspx
gonzobrains

2
당신이했습니다 자바 배경에서 이곳으로 온다면, 이것은이다 c#.net수행하는 방법 Object xyz = Class.forName(className).newInstance();.
SNag

여기에 더 나은 문서가 있습니다 .
jpaugh apr

답변:


149

MyFancyObject아래와 같은 클래스가 있다고 가정합니다 .

class MyFancyObject
{
 public int A { get;set;}
}

그것은 당신을 돌릴 수 있습니다 :

String ClassName = "MyFancyObject";

으로

MyFancyObject obj;

사용

obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))

그런 다음 다음과 같은 작업을 수행 할 수 있습니다.

obj.A = 100;

그것이 그 목적입니다. 또한 Type문자열에 클래스 이름 대신를 제공하는 것과 같은 많은 다른 오버로드가 있습니다. 왜 그런 문제가 발생하는지는 다른 이야기입니다. 필요한 사람들은 다음과 같습니다.


2
이것은 나에게 유용하다는 것이 증명되었습니다. 제 경우에는 클래스가 다른 네임 스페이스에 있었기 때문에 ClassName 문자열 (예 :)에 네임 스페이스를 포함했는지 확인해야했습니다 String ClassName = "My.Namespace.MyFancyObject";.
Scott

1
Unwrap ()을 추가하는 것을 잊었습니다. "MyAssembly"대신 null을 입력 할 수도 있으며 시스템은 현재 Assembly를 검색합니다.
Tony

1
이런 식으로 할 수 obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))있지만 유형으로 캐스팅하는 대신. ClassName에서 만든 유형으로 캐스트 하시겠습니까? 이렇게 Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))?
rluks

1
위와 다른 점 : MyFancyObject obj = new MyFancyObject?
Ed Landau

1
@Ed Landau 차이점은 컴파일 타임에 유형을 모르는 개체를 런타임에 인스턴스화 할 수 있다는 것입니다. 예를 들어 프로그램을위한 플러그인 시스템을 구축하는 경우. 답변의 링크는 MyFancyObject obj = new MyFancyObject () 작성이 불가능할 때에 대한 몇 가지 아이디어를 제공 할 수 있습니다. 이것은 종종 일반적으로 반사의 사용과 결합됩니다. 또 다른 설명은 stackoverflow.com/questions/9409293/… 에서도 확인할 수 있습니다 .
deepee1

47

왜 그런 것을 사용하는지 예를 들어 드릴 수 있습니다. 레벨과 적을 XML 파일에 저장하려는 게임을 생각해보십시오. 이 파일을 구문 분석 할 때 다음과 같은 요소가있을 수 있습니다.

<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>

지금 할 수있는 것은 레벨 파일에있는 오브젝트를 동적으로 생성하는 것입니다.

foreach(XmlNode node in doc)
   var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);

이것은 동적 환경을 구축하는 데 매우 유용합니다. 물론 플러그인이나 애드 인 시나리오 등에 사용할 수도 있습니다.


5
유형의 새 인스턴스를 만드는 것이 었음을 이해했지만 이것이 왜 그렇게 하려는지에 대한 좋은 간단한 예입니다.
jamiebarrow 2012

14

내 좋은 친구 MSDN 이 예를 들어 설명 할 수 있습니다.

향후 링크 또는 내용이 변경되는 경우 코드는 다음과 같습니다.

using System;

class DynamicInstanceList
{
    private static string instanceSpec = "System.EventArgs;System.Random;" +
        "System.Exception;System.Object;System.Version";

    public static void Main()
    {
        string[] instances = instanceSpec.Split(';');
        Array instlist = Array.CreateInstance(typeof(object), instances.Length);
        object item;
        for (int i = 0; i < instances.Length; i++)
        {
            // create the object from the specification string
            Console.WriteLine("Creating instance of: {0}", instances[i]);
            item = Activator.CreateInstance(Type.GetType(instances[i]));
            instlist.SetValue(item, i);
        }
        Console.WriteLine("\nObjects and their default values:\n");
        foreach (object o in instlist)
        {
            Console.WriteLine("Type:     {0}\nValue:    {1}\nHashCode: {2}\n",
                o.GetType().FullName, o.ToString(), o.GetHashCode());
        }
    }
}

// This program will display output similar to the following: 
// 
// Creating instance of: System.EventArgs 
// Creating instance of: System.Random 
// Creating instance of: System.Exception 
// Creating instance of: System.Object 
// Creating instance of: System.Version 
// 
// Objects and their default values: 
// 
// Type:     System.EventArgs 
// Value:    System.EventArgs 
// HashCode: 46104728 
// 
// Type:     System.Random 
// Value:    System.Random 
// HashCode: 12289376 
// 
// Type:     System.Exception 
// Value:    System.Exception: Exception of type 'System.Exception' was thrown. 
// HashCode: 55530882 
// 
// Type:     System.Object 
// Value:    System.Object 
// HashCode: 30015890 
// 
// Type:     System.Version 
// Value:    0.0 
// HashCode: 1048575

1
MSDN에서 일어날 가능성이 거의 없으며 여기에 콘텐츠를 복사하는 것은 거의 저작권 위반입니다.)
Claus Jørgensen

13
네가 옳아. 개인적으로이 원칙이 더 나은 답을주기 위해 작용한다고 느낍니다. 나는 종종 현재 프로젝트에서 내 마음에 많이 떠올랐다. 저는 보통 간단하고 정확한 답변을 원하므로 중단 한 부분부터 계속할 수 있습니다. 나는 때때로 다른 기사로 연결되는 기사를 열어야하는 것을 싫어한다. 많은 응답자들은 많은 사람들이 불필요한 소개와 강연으로 여러 기사를 읽을 시간을 가지고 여기에 오지 않는다는 것을 깨닫지 못합니다. 좋은 기사의 중요한 부분을 간략하게 요약하는 것은 내가 본 최고의 답변 중 일부의 핵심입니다.
Aske B. 2013-06-26

10

당신은 또한 이것을 할 수 있습니다-

var handle = Activator.CreateInstance("AssemblyName", 
                "Full name of the class including the namespace and class name");
var obj = handle.Unwrap();

Unwrap ()은 누락 된 부분이었습니다. :)
토니

위와 같이 사용할 수있는 'Unwrap ()'메서드를 찾을 수 없습니다. 새로운 .NET API에서 변경된 사항이 있습니까?
Sam

여전히 시스템 네임 스페이스에 있습니다.
William

2
.Unwrap()정확히 무엇을 하고 이것이 다른 솔루션과 어떻게 관련되는지 에 대한 추가 설명을 제공 할 수 있습니까?
Jeroen Vannevel

@Sam 그것은 CreateInstance그것이 반환 하는 곳 의 다른 과부하에 System.Runtime.Remoting.ObjectHandle있습니다.
nawfal

9

다음은 좋은 예가 될 수 있습니다. 예를 들어 로거 세트가 있고 사용자가 구성 파일을 통해 런타임에서 사용할 유형을 지정할 수 있습니다.

그때:

string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;

또는 또 다른 경우는 엔티티를 생성하고 DB에서 수신 한 데이터에 의한 엔티티 초기화를 담당하는 공통 엔티티 팩토리가있는 경우입니다.

(의사 코드)

public TEntity CreateEntityFromDataRow<TEntity>(DataRow row)
 where TEntity : IDbEntity, class
{
   MethodInfo methodInfo = typeof(T).GetMethod("BuildFromDataRow");
   TEntity instance = Activator.CreateInstance(typeof(TEntity)) as TEntity;
   return methodInfo.Invoke(instance, new object[] { row } ) as TEntity;
}

이 작동하지 않습니다 typeof(loggerType)에 결과를loggerType is a variable and used like a type
Barkermn01

3

그만큼 Activator.CreateInstance 메서드는 지정된 매개 변수와 가장 일치하는 생성자를 사용하여 지정된 형식의 인스턴스를 만듭니다.

예를 들어 유형 이름을 문자열로 사용하고 해당 문자열을 사용하여 해당 유형의 인스턴스를 생성한다고 가정 해 보겠습니다. Activator.CreateInstance이것을 위해 사용할 수 있습니다 .

string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));

다음은 응용 프로그램을 자세히 설명하는 MSDN 문서입니다.

http://msdn.microsoft.com/en-us/library/wccyzw83.aspx


5
또는 그냥 사용할 수 있습니다 new Foo(). 나는 OP가 더 현실적인 예를 원했다고 생각합니다.
Konrad Rudolph

1
@Konrad에 동의합니다. 사용하는 이유 CreateInstance는 디자인 타임에 인스턴스화 할 개체 유형을 모르는 경우입니다. 이 예에서는 type Foo으로 캐스팅하고 있으므로 유형 임을 분명히 알 수 Foo있습니다. 당신이 할 수 있기 때문에 당신은 결코 이것을하지 않을 것 Foo foo = new Foo()입니다.
theyetiman

1

deepee1 및 this 를 기반으로 문자열에서 클래스 이름을 수락 한 다음이를 사용하여 LINQ를 사용하여 데이터베이스에 읽고 쓰는 방법은 다음과 같습니다. deepee1의 캐스팅 대신 "dynamic"을 사용합니다. 속성을 할당 할 수 있기 때문에 원하는 테이블을 동적으로 선택하고 작업 할 수 있습니다.

Type tableType = Assembly.GetExecutingAssembly().GetType("NameSpace.TableName");
ITable itable = dbcontext.GetTable(tableType);

//prints contents of the table
foreach (object y in itable) {
    string value = (string)y.GetType().GetProperty("ColumnName").GetValue(y, null);
    Console.WriteLine(value);
}

//inserting into a table
dynamic tableClass = Activator.CreateInstance(tableType);
//Alternative to using tableType, using Tony's tips
dynamic tableClass = Activator.CreateInstance(null, "NameSpace.TableName").Unwrap();
tableClass.Word = userParameter;
itable.InsertOnSubmit(tableClass);
dbcontext.SubmitChanges();

//sql equivalent
dbcontext.ExecuteCommand("INSERT INTO [TableNme]([ColumnName]) VALUES ({0})", userParameter);

0

이미 클래스를 알고 있고 캐스팅 할 예정이라면 왜 사용하겠습니까? 그냥 구식으로하고 항상 수업을하는 것처럼 만드는 게 어떨까요? 일반적으로 수행되는 방식에 비해 이점이 없습니다. 텍스트를 가져와 이에 따라 작동하는 방법이 있습니까?

label1.txt = "Pizza" 
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();

이미 피자를 알고 있다면 다음과 같은 이점이 없습니다.

p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();

하지만 매직 방법이 존재한다면 큰 장점이 있습니다.


0

리플렉션과 함께 Activator.CreateInstance가 다음 답변에 설명 된대로 저장 프로 시저 결과를 사용자 지정 클래스에 매핑하는 데 매우 유용하다는 것을 알았습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.