인스턴스화 된 System.Type을 제네릭 클래스의 형식 매개 변수로 전달 new MyGenericClass<myType>(); 분명히 MyGenericClass는 다음과 같이 설명됩니다. public

제목이 불분명합니다. 내가 알고 싶은 것은 이것이 가능한지입니다.

string typeName = <read type name from somwhere>;
Type myType = Type.GetType(typeName);

MyGenericClass<myType> myGenericClass = new MyGenericClass<myType>();

분명히 MyGenericClass는 다음과 같이 설명됩니다.

public class MyGenericClass<T>

현재 컴파일러는 ‘유형 또는 네임 스페이스’myType ‘을 찾을 수 없습니다’라고 불평합니다. “이를 수행 할 방법이 있어야합니다.



답변

당신은 반사없이 이것을 할 수 없습니다. 그러나 반사로 할 수 있습니다 . 다음은 완전한 예입니다.

using System;
using System.Reflection;

public class Generic<T>
{
    public Generic()
    {
        Console.WriteLine("T={0}", typeof(T));
    }
}

class Test
{
    static void Main()
    {
        string typeName = "System.String";
        Type typeArgument = Type.GetType(typeName);

        Type genericClass = typeof(Generic<>);
        // MakeGenericType is badly named
        Type constructedClass = genericClass.MakeGenericType(typeArgument);

        object created = Activator.CreateInstance(constructedClass);
    }
}

참고 : 일반 클래스가 여러 유형을 허용하는 경우 유형 이름을 생략 할 때 쉼표를 포함해야합니다. 예를 들면 다음과 같습니다.

Type genericClass = typeof(IReadOnlyDictionary<,>);
Type constructedClass = genericClass.MakeGenericType(typeArgument1, typeArgument2);

답변

불행히도 없습니다. 일반 인수는 컴파일시 1) 유효한 유형 또는 2) 다른 일반 매개 변수로 해석 할 수 있어야합니다. 리플렉션을 사용하지 않고도 런타임 값을 기반으로 일반 인스턴스를 만들 수있는 방법이 없습니다.


답변

가위 코드로 실행하는 몇 가지 추가 방법. 비슷한 클래스가 있다고 가정하십시오.

public class Encoder() {
public void Markdown(IEnumerable<FooContent> contents) { do magic }
public void Markdown(IEnumerable<BarContent> contents) { do magic2 }
}

런타임에 FooContent 가 있다고 가정하십시오.

컴파일 타임에 바인딩 할 수 있다면

var fooContents = new List<FooContent>(fooContent)
new Encoder().Markdown(fooContents)

그러나 런타임에는이 작업을 수행 할 수 없습니다. 런타임에이를 수행하려면 다음 라인을 수행하십시오.

var listType = typeof(List<>).MakeGenericType(myType);
var dynamicList = Activator.CreateInstance(listType);
((IList)dynamicList).Add(fooContent);

동적으로 호출하려면 Markdown(IEnumerable<FooContent> contents)

new Encoder().Markdown( (dynamic) dynamicList)

dynamic메소드 호출에서 의 사용법에 유의하십시오 . 런타임시 dynamicList됩니다 List<FooContent>(추가도되고 IEnumerable<FooContent>동적조차 사용은 여전히 런타임 바인더는 적절한 선택하는 강력한 형식의 언어에 뿌리를두고 있기 때문에) Markdown방법을. 정확히 일치하는 유형이 없으면 객체 매개 변수 메소드를 찾고 런타임 바인더 예외와 일치하지 않으면 메소드가 일치하지 않는다는 경고를 발생시킵니다.

이 접근 방식의 명백한 단점은 컴파일 타임에 유형 안전이 크게 손실된다는 것입니다. 그럼에도 불구하고 이러한 행을 따르는 코드를 사용하면 런타임에 예상대로 여전히 완전히 입력되었음을 매우 역동적으로 이해할 수 있습니다.


답변

내 요구 사항이 약간 다르지만 희망적으로 누군가를 도울 것입니다. 구성에서 유형을 읽고 일반 유형을 동적으로 인스턴스화해야했습니다.

namespace GenericTest
{
    public class Item
    {
    }
}

namespace GenericTest
{
    public class GenericClass<T>
    {
    }
}

마지막으로 여기에 전화하는 방법이 있습니다. 백틱으로 유형을 정의하십시오 .

var t = Type.GetType("GenericTest.GenericClass`1[[GenericTest.Item, GenericTest]], GenericTest");
var a = Activator.CreateInstance(t);

답변

어떤 타입이 전달 될지 안다면, 이것을 반영하지 않고 이것을 할 수 있습니다. 스위치 문이 작동합니다. 분명히 이것은 제한된 수의 경우에만 작동하지만 리플렉션보다 훨씬 빠릅니다.

public class Type1 { }

public class Type2 { }

public class Generic<T> { }

public class Program
{
    public static void Main()
    {
        var typeName = nameof(Type1);

        switch (typeName)
        {
            case nameof(Type1):
                var type1 = new Generic<Type1>();
                // do something
                break;
            case nameof(Type2):
                var type2 = new Generic<Type2>();
                // do something
                break;
        }
    }
}

답변

이 스 니펫에서는 동적으로 작성된 목록을 작성하고 사용하는 방법을 보여 드리고자합니다. 예를 들어 여기 동적 목록에 추가하고 있습니다.

void AddValue<T>(object targetList, T valueToAdd)
{
    var addMethod = targetList.GetType().GetMethod("Add");
    addMethod.Invoke(targetList, new[] { valueToAdd } as object[]);
}

var listType = typeof(List<>).MakeGenericType(new[] { dynamicType }); // dynamicType is the type you want
var list = Activator.CreateInstance(listType);

AddValue(list, 5);

마찬가지로 목록에서 다른 방법을 호출 할 수 있습니다.