문자열 표현에서 제네릭 유형을 어떻게 얻을 수 있습니까?


79

나는 MyClass<T>.

그리고 나는 이것을 가지고 있습니다 string s = "MyClass<AnotherClass>";. 문자열에서 유형을 어떻게 얻을 수 s있습니까?

한 가지 방법 (못생긴)은 "<"및 ">"를 구문 분석하고 다음을 수행하는 것입니다.

Type acType = Type.GetType("AnotherClass");  
Type whatIwant = typeof (MyClass<>).MakeGenericType(acType);

그러나 구문 분석 등을 수행하지 않고 최종 유형을 얻는 더 깨끗한 방법이 있습니까?

답변:


94

제네릭형식 은 이름,`문자, 유형 매개 변수 수, 쉼표로 구분 된 괄호로 구분 된 유형 목록입니다.

Type.GetType("System.Collections.Generic.IEnumerable`1[System.String]");

제네릭의 C # 구문에서 CLR이 원하는 종류의 문자열로 쉽게 변환 할 수있는 방법이 있는지 잘 모르겠습니다. 질문에서 언급 한 것처럼 구문 분석을 위해 빠른 정규식을 작성하기 시작했지만 유형 매개 변수로 중첩 된 제네릭을 갖는 기능을 포기하지 않으면 구문 분석이 매우 복잡해질 것임을 깨달았습니다.


+1-좋은 답변, 감사합니다! 나는 제네릭을 다루는 방법을 찾으려고 애 쓰고 있었다!
marc_s

감사. 이것은 작동하며 이러한 방식으로 문자열을 형식화하도록 코드를 수정해야합니다. 그러나 "MyClass <AnotherClass>"를 단순히 사용하는 방법이 여전히 있는지 궁금합니다. "MyClass <AnotherClass>"는 Type 인스턴스를 가져 오기 위해 문자열에 표시되는 방식과 동일합니다. 훨씬 깨끗해 보입니다.
DeeStackOverflow 2009

이런 식으로 문자열 형식을 지정하기 위해 코드를 수정할 필요가 없습니다. Type에서 ToString ()을 호출하기 만하면됩니다.
Rush Frisby

38

체크 아웃 Activator.CreateInstance-당신은 유형으로 부를 수 있습니다

Activator.CreateInstance(typeof(MyType))

또는 어셈블리 및 유형 이름을 string

Activator.CreateInstance("myAssembly", "myType")

그러면 필요한 유형의 인스턴스가 제공됩니다.

Type인스턴스 가 아니라 필요한 경우 Type.GetType()메서드와 관심있는 유형의 정규화 된 이름을 사용합니다. 예 :

string s = "System.Text.StringBuilder";
Type myClassType = Type.GetType(s);

그것은 당신에게 Type문제를 줄 것 입니다.


3
이것은 코드 스 니펫을 기반으로 OP가 찾고있는 것처럼 보이는 System.Type 인스턴스가 아닌 유형의 인스턴스를 가져옵니다.
Daniel Schaffer

26

나는 이와 같은 것이 필요했고 필요한 간단한 유형 이름을 구문 분석하기 위해 코드를 작성했습니다. 물론, 같은 제네릭 유형 이름을 식별하지 않기 때문에 개선의 여지가 List<string>있지만 string, int[]등에서 는 괜찮습니다 decimal?. 이것이 누구에게나 도움이 될 경우 공유합니다.

public static class TypeExtensions
{
  public static Type GetTypeFromSimpleName(string typeName)
  {
    if (typeName == null)
      throw new ArgumentNullException("typeName");

    bool isArray = false, isNullable = false;

    if (typeName.IndexOf("[]") != -1)
    {
      isArray = true;
      typeName = typeName.Remove(typeName.IndexOf("[]"), 2);
    }

    if (typeName.IndexOf("?") != -1)
    {
      isNullable = true;
      typeName = typeName.Remove(typeName.IndexOf("?"), 1);
    }

    typeName = typeName.ToLower();

    string parsedTypeName = null;
    switch (typeName)
    {
      case "bool":
      case "boolean":
        parsedTypeName = "System.Boolean";
        break;
      case "byte":
        parsedTypeName = "System.Byte";
        break;
      case "char":
        parsedTypeName = "System.Char";
        break;
      case "datetime":
        parsedTypeName = "System.DateTime";
        break;
      case "datetimeoffset":
        parsedTypeName = "System.DateTimeOffset";
        break;
      case "decimal":
        parsedTypeName = "System.Decimal";
        break;
      case "double":
        parsedTypeName = "System.Double";
        break;
      case "float":
        parsedTypeName = "System.Single";
        break;
      case "int16":
      case "short":
        parsedTypeName = "System.Int16";
        break;
      case "int32":
      case "int":
        parsedTypeName = "System.Int32";
        break;
      case "int64":
      case "long":
        parsedTypeName = "System.Int64";
        break;
      case "object":
        parsedTypeName = "System.Object";
        break;
      case "sbyte":
        parsedTypeName = "System.SByte";
        break;
      case "string":
        parsedTypeName = "System.String";
        break;
      case "timespan":
        parsedTypeName = "System.TimeSpan";
        break;
      case "uint16":
      case "ushort":
        parsedTypeName = "System.UInt16";
        break;
      case "uint32":
      case "uint":
        parsedTypeName = "System.UInt32";
        break;
      case "uint64":
      case "ulong":
        parsedTypeName = "System.UInt64";
        break;
    }

    if (parsedTypeName != null)
    {
      if (isArray)
        parsedTypeName = parsedTypeName + "[]";

      if (isNullable)
        parsedTypeName = String.Concat("System.Nullable`1[", parsedTypeName, "]");
    }
    else
      parsedTypeName = typeName;

    // Expected to throw an exception in case the type has not been recognized.
    return Type.GetType(parsedTypeName);
  }
}

이것을 사용하는 것은 다음과 같이 작성하는 것만 큼 간단합니다.

Type t;

t = TypeExtensions.GetTypeFromSimpleName("string");
t = TypeExtensions.GetTypeFromSimpleName("int[]");
t = TypeExtensions.GetTypeFromSimpleName("decimal?");

1
짧고, 완벽하고, 매우 유용합니다! 감사합니다
xrnd 2014

3

문자열에서 유형 객체를 가져 오려면 다음을 사용하십시오.

Type mytype = Type.GetType(typeName);

그런 다음 이것을 다음으로 전달할 수 있습니다 Activator.CreateInstance().

Activator.CreateInstance(mytype);

0

비슷한 답변을 본 것 같지만 이것을 파싱 할 시간이 많지 않습니다. 특히, 나는 그들이 여기서 당신이 원하는 것을 정확히하고 있다고 생각합니다.

Entity Framework 일반 리포지토리 오류

(String.Format("[{0}]", baseType.Name.ToString())).OfType<T>();

도움이 되었기를 바랍니다. 그렇지 않은 경우 더 구체적으로 알려주세요.

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