문제

아래와 같은 수업이 있습니다.

class Foo
{
  public Foo(int x) { ... }
}

그리고 나는 다음과 같은 대의원을 특정 방법으로 전달해야합니다.

delegate Foo FooGenerator(int x);

생성자를 직접 전달할 수 있습니까? FooGenerator 입력 할 필요없이 값 :

delegate(int x) { return new Foo(x); }

?

편집하다: 개인적으로 사용하기 위해이 질문은 .NET 2.0을 말하지만 3.0+에 대한 힌트/응답도 환영합니다.

도움이 되었습니까?

해결책

아니, CLR은 구속력있는 대의원을 허용하지 않습니다. ConstructorInfo.

그러나 자신만의만을 만들 수 있습니다.

static T Make<T>(Action<T> init) where T : new()
{
  var t = new T();
  init(t);
  return t;
}

용법

var t = Make<Foo>( x => { x.Bar = "bar"; x.Baz = 1; });

다른 팁

나는 당신이 일반적으로 컴파일 타임에서 실제 유형을 알려지지 않은 공장 구현의 일부로 이와 같은 일을한다고 가정합니다 ...

먼저, 더 쉬운 접근 방식은 제작 후 초기 단계 일 수 있으며 제네릭을 사용할 수 있습니다.

static T Create<T>({args}) where T : class, ISomeInitInterface, new() {
    T t = new T();
    t.Init(args);
    return t;
}

그런 다음 사용할 수 있습니다 MakeGenericMethod 및/또는 CreateDelegate.


그렇지 않으면; 당신은이 작업을 즉석에서 할 수 있습니다 Expression (3.5) 또는 DynamicMethod (2.0).

그만큼 Expression 접근 방식은 코딩하기가 더 쉽습니다.

    var param = Expression.Parameter(typeof(int), "val");
    var ctor = typeof(Foo).GetConstructor(new[] { typeof(int) });
    var lambda = Expression.Lambda<Func<int, Foo>>(
        Expression.New(ctor, param), param);
    var func = lambda.Compile();
    Foo foo = func(123);
    string s = foo.ToString(); // proof

또는 (사용 DynamicMethod):

    ConstructorInfo ctor = typeof(Foo).GetConstructor(new[] { typeof(int) });
    DynamicMethod dm = new DynamicMethod("Create", typeof(Foo),
            new Type[] { typeof(int) }, typeof(Foo), true);
    ILGenerator il = dm.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Newobj, ctor);
    il.Emit(OpCodes.Ret);
    Converter<int, Foo> func = (Converter<int, Foo>)
        dm.CreateDelegate(typeof(Converter<int, Foo>));        
    Foo foo = func(123);
    string s = foo.ToString(); // proof

공장 패턴으로 이동하지 않고 간결한 것으로 생각합니다.

delegate Foo FooGenerator(int x);

...    

void DoStuff()
{
    YourDelegateConsumer(x => new Foo(x));
}

이것은 당신이 요청한 일을 엄격하게 수행하지 않습니다 (대의원을 대표를 생성자에게 직접 대의원이 아닌 새로운 인스턴스를 반환하는 익명 방법으로 전달하기 때문에). 엄격하게 가능합니다.

물론 이것은 3.5+를 사용하고 있다고 가정합니다.

클래스 공장 패턴을 사용하고 싶을 것 같습니다.

공장 방법 패턴

불행히도, 생성자는 방법과 동일하지 않으므로 그들을 가리키는 대의원을 만들 수 없습니다. 이것은 흥미로운 아이디어이지만, 아마도 더 많은 정보를 통해 우리는 구문 적으로 유사한 일종의 해결 방법을 고안 할 수 있습니다.

Marc Gravell의 답변은 다음과 같은 매우 간단한 해결책에 영감을주었습니다.

static void Main()
{
    Pet a = _MakeObject(typeof(Dog));
    Pet b = _MakeObject(typeof(Cat));
}

private static Pet _MakeObject(Type type)
{
    ConstructorInfo info = type.GetConstructor(new Type[0]);
    return (Pet)info?.Invoke(null);
}

생성자가 매개 변수가있는 경우 (이 예에서 : 1 유형 int의 매개 변수) :

static void Main()
{
    Pet a = _MakeObject(typeof(Dog), 5);
    Pet b = _MakeObject(typeof(Cat), 7);
}

private static Pet _MakeObject(Type type, int age)
{
    ConstructorInfo info = type.GetConstructor(new [] { typeof(int) });
    return (Pet)info?.Invoke(new object[] { age });
}

내 생각에 아직 생성되지 않은 객체의 방법을 통과하기 때문에 불가능하다는 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top