2010-07-30 4 views
2

나는 다음과 같은 테스트 클래스가 있습니다제네릭에 인터페이스를 동적으로 배치하는 방법은 무엇입니까?

public class OutsideClass 
{ 
    private List<Type> _interfaces = null; 

    public void InjectInterfaces(Type[] types) 
    { 
     if(_interfaces == null) 
     { 
      _interfaces = new List<Type>(); 
     } 

     foreach (var type in types) 
     { 
      if(type.IsInterface) 
      { 
       _interfaces.Add(type); 
      } 
     } 
    } 

    public void PerformSomethingWithTheInterfaces() 
    { 
     foreach (var i in _interfaces) 
     { 
      new Test<i>().PerformSomething(); // On this line the error occurs 
     } 
    } 
} 

internal class Test<T> 
{ 
    internal void PerformSomething() 
    { 

    } 
} 

이 그러나 메시지 Type or namespace name expected 날에 제공합니다. 어떻게 작동하도록이 코드를 조정할 수 있습니까?

내가 뭘하려는 건 클래스 라이브러리에 인터페이스의 무리를 통과하고 거기에 유니티을 사용하여 인터페이스를 기반으로 해결합니다. Resolve Extension 메서드를 사용합니다.

+0

여기서 수행하려는 작업에 대해 설명해 주시겠습니까? –

답변

0

일반 인수로 값을 전달할 수 없습니다. 유형 만. 명확하게하려면 :

typeof (string)! = string.

+0

당신이 문자열을 호출 한 것은'System.String'이 아니라 C# 토큰입니다. –

0

나는 이것이 작동하지 않는다고 생각합니다. 유형 이름에 제네릭을 정적으로 적용 할 수 있습니다. Type 개체에 대한 참조를 전달할 수 없습니다.

원하는 작업을 수행 할 수있는 방법이 있지만 C# 4 및 DynamicObject이 있습니다.

+0

Skeet의 답은 당연한 것입니다.하지만 그는 '동적'의 숨겨진 반영 대신 완전히 반사를 사용하고 있습니다. 'PerformSomethingWithTheInterfaces'를 동적으로 만들 수 있기 때문에 후자를 선호합니다. –

+0

불행히도 .NET 3.5에 아직도 있습니다. 그러나 나중에 참조 할 수 있도록 DynamicObject를 사용하는 샘플이 있습니까? –

+0

'Test '의 인스턴스를 만들기 위해 동적 타이핑을 사용하는 경우에도 리플렉션을 사용해야합니다. –

3

당신은 반사를 사용해야 할 것 ... 이런 일이 :

foreach (Type type in _interfaces) 
{ 
    Type concreteType = typeof(Test<>).MakeGenericType(new Type[] { type }); 
    MethodInfo method = concreteType.GetMethod("PerformSomething", 
     BindingFlags.Instance | BindingFlags.NonPublic); 
    object instance = Activator.CreateInstance(concreteType); 
    method.Invoke(instance, null); 
} 

(당신은 사소한 변경해야 할 수도 있습니다 - 위의 테스트 또는 컴파일되지 않습니다.)

으로 C# 4 및 동적 입력, 당신은 다소 간단하게 만들 수 있습니다

foreach (Type type in _interfaces) 
{ 
    Type concreteType = typeof(Test<>).MakeGenericType(new Type[] { type }); 
    dynamic d = Activator.CreateInstance(concreteType); 
    d.PerformSomething(); 
} 
+0

와우, 발굴하지만 나는 그것을 줄 것이다. 시험. 이걸 도와 주셔서 고마워요. –

+0

물론, 이것 (또는 이것에 매우 근접한 것)이 작동합니다. 그러나 나는 OP의 의도에 어떤 의도가 있는지 궁금합니다. 나는 당신이 틀린 질문에 정당한 대답을했다는 느낌을 받는다. –

0

당신은 정말 그냥 유니티 교체로 생각 나는 그것이 정말 잘 자신과 simplif 버틴다 생각하는 C# 4의 MEF에서 볼 수도 있습니다 해결 방법이 많아서 더 간단하게하려는 작업을 완료 할 수있는 기능을 제공 할 수 있습니다.

namespace MEF_Interface 
{ 
    // Interface to recognize the concrete implementation as 
    public interface IMessageWriter 
    { 
     void WriteMessage(); 
    } 

} 

namespace MEF_HelloMessageWriter 
{ 
    // Concrete implementation in another assembly 
    [Export(typeof(IMessageWriter))] 
    public class HelloMessageWriter : IMessageWriter 
    { 
     public void WriteMessage() { Console.WriteLine("Hello!"); } 
    } 
} 

namespace MEF_GoodbyeMessageWriter 
{ 
    // Concrete implementation in another assembly 
    [Export(typeof(IMessageWriter))] 
    public class GoodbyeMessageWriter : IMessageWriter 
    { 
     public void WriteMessage() { Console.WriteLine("Goodbye!"); } 
    } 
} 

namespace MEF_Example 
{ 
    class DIContainer 
    { 
     [Import] 
     public IMessageWriter MessageWriter { get; set; } 

     public DIContainer(string directory) 
     { 
      // No more messy XML DI definition, just a catalog that loads 
      // all exports in a specified directory. Filtering is also available. 
      DirectoryCatalog catalog = new DirectoryCatalog(directory); 
      catalog.Refresh(); 
      var container = new CompositionContainer(catalog); 
      container.ComposeParts(this); 
     } 
    } 

    class Program 
    { 

     static void Main(string[] args) 
     { 
      string helloMessageWriterPath = 
       @"C:\shared\Projects\MEF_Example\MEF_HelloMessageWriter\bin\Debug"; 

      string goodbyeMessageWriterPath = 
       @"C:\shared\Projects\MEF_Example\MEF_GoodbyeMessageWriter\bin\Debug"; 

      DIContainer diHelloContainer = new DIContainer(helloMessageWriterPath); 
      diHelloContainer.MessageWriter.WriteMessage(); 

      DIContainer diGoodbyeContainer = new DIContainer(goodbyeMessageWriterPath); 
      diGoodbyeContainer.MessageWriter.WriteMessage(); 

      Console.ReadLine(); 
     } 
    } 
} 
+0

이것은 재미 있지만 OP와 관련이 있는지 잘 모르겠습니다. 그리고 다시, 나는 OP를 정말로 이해하지 못한다. 그래서 나는 쉽게 착각 할 수있다. –

+0

그것은 내가 느낀 것과 같은 종류입니다. 나는 OP가 자신이 원하는 것을 알고 있는지 확신하지 못하기 때문에 이것이 도움이 될 수 있습니다. –

+0

@ 지미 : 귀하의 의견 앞에 "@"와 사용자 이름을 붙여주십시오. 그렇지 않으면 질문이나 답변이 아닌 한 알림을받지 못합니다. –

관련 문제