문제

런타임에 생성 된 유형 (Codedom의 컴파일을 통해)이 있고 알려진 (컴파일 타임) 인터페이스를 구현합니다.

인터페이스가 있다고 가정합니다 IMyInterface, 그리고 유형 인스턴스가 있습니다 Type myType 내가 어셈블리에서 획득 한 것은 방금 코드에서 편집했습니다. 그 수업 myType 도구를 나타냅니다 IMyInterface.

대표를 받고 싶습니다 Func<IMyInterface> 호출되면 인스턴스를 반환합니다. myType.

이런 식으로 전화하고 싶은 것 :

Func<IMyInterface> createObject = GetObjectCreator<IMyInterface>(myType);
IMyInterface myObject = createObject();

나는 내가 있다는 것을 알고있다 MethodInfo m MyType 객체의 인스턴스를 반환하는 매개 변수가없는 메소드의 경우 다음과 같은 작업을 수행 할 수 있습니다.

Func<IMyInterface> createObject =
  ( Func<IMyInterface> )Delegate.CreateDelegate(typeof(Func<IMyInterface>), m);

그러나 그런 방법이없고 내가 가진 유일한 것은 유형의 매개 변수가없는 생성자라면 어떻게이 대의원을 얻습니까?

업데이트

Fsimonazzi의 대답은 내가 요구 한 일을 정확하게 수행했지만 내 접근 방식은 약간 달랐습니다.

나는 생성과 편집을 제어하기 때문에 myType 유형, 해당 유형의 인스턴스를 반환하는 공개 정적 메소드를 추가했습니다. 그런 다음이 유형을 컴파일 한 후이 메소드에 대한 MethodInfo 인스턴스를 얻었고 원하는 대의원 전화 대의원을 만들었습니다.

CodeTypeDeclaration type = new CodeTypeDeclaration
{
    Name = "MyClass",
    IsClass = true,
    TypeAttributes = TypeAttributes.Public
};

type.BaseTypes.Add(new CodeTypeReference(typeof(IMyInterface)));

// fullName is the full name of the myType (including namespace)
var staticInstantiator = new CodeMemberMethod
{
    Name = "__Instantiator",
    ReturnType = new CodeTypeReference("MyNamespace.MyClass"),
    Attributes = MemberAttributes.Public | MemberAttributes.Static
};

staticInstantiator.Statements.Add(
   new CodeMethodReturnStatement(
       new CodeObjectCreateExpression("MyNamespace.MyClass")));

    type.Members.Add(staticInstantiator);

위의 코드는이 코드를 생성하고 클래스 선언에 들어갑니다.

public static MyNamespace.MyClass __Instantiator()
{
    return new MyNamespace.MyClass();
}

이제이 코드를 컴파일하고 a myType 이 클래스의 인스턴스를 입력하십시오

Func<IMyInterface> createObject = ( Func<IMyInterface> )(
    Delegate.CreateDelegate(typeof(Func<IMyInterface>),
                            myType.GetMethod("__Instantiator")) );

IMyInterface obj = createObject(); // This will call MyClass.__Instantiator()
도움이 되었습니까?

해결책

간단한 람다 표현식을 컴파일하여 대표를 얻을 수 있습니다.

var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();

다른 팁

당신이 사용할 수있는 Activator.CreateInstance( type ) 실제로 유형의 인스턴스를 만듭니다. 당신이 이것을 원한다면 a Func<IMyInterface> 그런 다음 람다로 감을 수 있습니다.

Func<IMyInterface> createObject = () => (IMyInterface) Activator.CreateInstance( myType );
IMyInterface myObject = createObject();

업데이트:

부터 Activator.CreateInstance 분명히 당신이 찾고있는 것이 아닙니다.

public Func<T> GetObjectCreator<T>( Type type )
{
    // I'd probably add additional checks here to see that the
    // conversion to T is actually possible.

    var ctor = type.GetConstructor( Type.EmptyTypes );

    if( ctor == null ) throw new ArgumentException( "type", "Public parameterless constructor not found." )

    return () => (T) ctor.Invoke( null );
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top