간단한 람다 표현식을 컴파일하여 대표를 얻을 수 있습니다.
var del = Expression.Lambda<Func<IMyInterface>>(Expression.New(type)).Compile();
문제
런타임에 생성 된 유형 (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 );
}