2009-11-03 3 views
5

내가 문제를 해결하는 방법을 찾고 있어요 나는이 모든 C#을 &는 .NET 3.5에서 할 수 있습니다 모르겠어요 :C# 런타임에 동적으로 다른 인터페이스를 구현하는 객체를 생성하는 방법은 무엇입니까?

내가 인터페이스의 제한된 수의이 말, 각각의 특정을 설명, 비 관련 세트 이제는 각각 실제 인터페이스 장치의 일부만 구현할 수있는 실제 장치가 있습니다.

이러한 장치로 통신을 설정하는 동안 해당 장치에 어떤 기능이 있는지 알 수 있습니다. 상기 인터페이스에 대한

  • 코드를 작성
  • 테스트 : 나는 할 수있어 내 응용 프로그램 아키텍처에서 최대 높은 있도록 지금 인터페이스 (장치의 각 닮은 한 기능)을 구현하는 객체를 생성하고 싶습니다 생성 된 객체가 특정 작업을 지원하는지 확인하기 위해 특정 인터페이스를 구현하는 경우

이 문제에 대해 어떤 접근 방식을 사용할지 잘 모르겠습니다. 가장 환영받는 의견이나 접근법!

+0

첫째, 귀하의 의견과 제안에 대해 모두 감사드립니다. 대단히 감사합니다! 좋아, 내가 직면하고있는 문제에 대해 좀 더 자세히 설명해야한다고 생각한다. 특정 기능을 보유하고 있습니다 (예 : CanMakeCoffe, CanCleanKitchen 등 대부분의 기기에서 구현되는 몇 가지 기능이 있습니다 (예 : CanMakeCoffee. 내가 피할 싶은 것이 는 CDeviceOne에서 이러한 장치에 대한 소스 코드 클래스 어딘가에 정의하는 것입니다 : ICanMakeCoffee, ICanCleanKitchen CDeviceTwo : ICanMakeCoffee –

+0

차라리 그들이 무엇을 할 수 있는지에 연결하면 장치가 말해 거라고 그리고 나는 그들의 능력과 닮은 대상을 창조 할 것입니다. 의미가 있습니까? –

답변

3

LinFu.DynamicObject과 같은 것을 시도해보십시오.

+0

실제로 매우 흥미 롭습니다. 나는 특히 믹스 인을 만드는 아이디어를 좋아합니다. 나는 생산 코드를 위해 그런 종류의 프레임 워크를 사용하는 것을 주저하고있다. 라이센스를 봐야 할 것이다. 어쨌든 그 덕분에! –

+0

LGPL 라이센스입니다. 그리고 필립에게 감사해야합니다. :) –

5

사용하십시오 mocking framework 같은 당신이 뭔가를 낮은 수준을 찾고 있다면 RhinoMocks, Moq 또는 TypeMock Isolator

, Castle DynamicProxy 같은 것들을 당신을 위해 좋은 방향이 될 수 있습니다.

+2

오리 입력을 검색하면 결과가 나올 수도 있습니다. – leppie

+0

@leppie : 아주 좋은 지적입니다. @Timo : IronPython 또는 IronRuby (또는 C# 4의 동적 관련 항목)와 같은 동적 언어를 사용하는 경우 유용한 인터페이스를 구현할 수 있습니다 (실제 '인터페이스'정의를 사용하지 않겠지 만). '구현에서 –

+0

@leppie : 당신의 제안에 감사드립니다. 나는 이미 오리 타이핑을 보았습니다. 그러나 문제가있는 데 도움이되는지 확신 할 수 없었습니다. 어쨌든 다시 살펴볼 것입니다! @Ruben : DynamicProxy에 대한 귀하의 포인터를 보내 주셔서 감사합니다. 가장 흥미로운! 나는 또한 더 자세히 살펴볼 것이다. –

0

쉽지 않을 수도 있습니다. 기본적으로 소스 파일 인 문자열을 만든 다음 CSharpCodeProvider를 만들고 사용하여 코드를 컴파일해야합니다. 작동하는 경우 반영을 통해 생성 된 객체에 수동으로 액세스 할 수 있습니다.

관심이 있으시면 잠시 후에 자세히 보았습니다. 세부 사항은 다소 안개가 듭니다.

+2

il-code를 메모리의 동적 어셈블리로 내보내는 것이 쉽습니다. 그러나, mocking 프레임 워크는 이것을 더 쉽고/덜 코드화 할 수 있습니다. ;) – sisve

1

아마도 "동적"으로 설정할 필요는 없습니다.

Abstract Factory 패턴을 확인 했습니까? 기본적으로 필요한 것은 장치 을 기반으로 각 인터페이스에 대한 구체적인 구현을 만드는 것입니다.

많은 인터페이스를 구현하는 단일 클래스를 가질 필요는 없지만 코드에서 요청할 때 특정 인터페이스를 적절히 구현하면 충분합니다.

추상 팩토리를 구현할 때마다 디바이스 유형에 따라 여러 인터페이스 구현을 생성 할 수 있습니다.

예 :

public interface IDeviceFactory 
{ 
     ISomething GetSomeInterface(); 
     ISomethingElse GetSomeOtherInterface(); 
} 

한 다음 각 장치에 대한 특정 공장 구현 :

public class SimpleDeviceFactory : IDeviceFactory 
{ 
    public virtual ISomething GetSomeInterface() 
    { return Something.Empty; } 

    public virtual ISomethingElse GetSomeOtherInterface() 
    { return new SomeSimpleConreteImplementation(); } 
} 

아니면 : 다음

public class ComplexDeviceFactory : IDeviceFactory 
{ 
    public virtual ISomething GetSomeInterface() 
    { return new ComplexStuff(); } 

    public virtual ISomethingElse GetSomeOtherInterface() 
    { return new EvenMoreComplexStuff(); } 
} 

그리고를, 마지막으로, 당신은 바로를 만들 기기 용 공장 :

public class DeviceFactory 
{ 
    public static IDeviceFactory CreateForDevice(IDevice device) 
    { 
      DeviceType type = device.Type; // or something like this 
      switch (type) 
      { 
       case DeviceType.Simple: 
       return new SimpleDeviceFactory(); 

       case DeviceType.Complex: 
       return new ComplexDeviceFactory(); 

       default: 
       throw new NotImplementedException(); 
      } 
    } 
} 

IDeviceFactory 메서드 구현을 virtual으로 표시 했으므로 특정 장치의 특정 인터페이스를 쉽게 다시 사용하거나 재정의 할 수 있습니다.

+0

그로 고마워. 정말 문제에 대한 직접적인 접근입니다! 원래 질문에 대한 내 의견을 말한대로 모든 장치에 대한 클래스를 만드는 "장치 중심"이라는 코드를 작성하지 않고 장치의 피드백을 기반으로 만들어진 개체를 만들려고합니다. 해야 할 것). –

0

.NET 4를 사용하면 이미 언급 한 프레임 워크 중 하나를 사용하거나 System.Reflection 경로를 사용할 수 있습니다. 인터넷에서 많은 샘플을 찾을 수 있습니다.

나는 둘 다 과거에 해왔습니다. 내 자신의 il을 롤링합니다. 물건을 가져오고 프레임 워크 (제 경우에는 Spring.NET)를 사용하십시오. 사소한 것들을 제외하고는 프레임 워크 중 하나를 사용하십시오.

0

Re-mix 프로젝트를 사용해 볼 수도 있습니다. 이 프로젝트의 주요 기능 중 하나는 mixins 작성이며 구현 및 상태가있는 인터페이스를 다른 클래스에 추가 할 수있게 해줍니다.

using Remotion.Mixins; 
using Remotion.TypePipe; 
//... 

public interface ITargetInterface 
{ 
    void DoSomething(); 
} 
// . . . 
public class TargetImplementation : ITargetInterface 
{ 
    public void DoSomething() 
    { 
     Console.WriteLine("ITargetInterface.DoSomething()"); 
    } 
} 
// . . . 
public interface IMixinInterfaceA 
{ 
    void MethodA(); 
} 
// . . . 
public class MixinImplementationA : IMixinInterfaceA 
{ 
    public void MethodA() 
    { 
     Console.WriteLine("IMixinInterfaceA.MethodA()"); 
    } 
} 
// . . . 
public interface IMixinInterfaceB 
{ 
    void MethodB(int parameter); 
} 

// . . . 
public class MixinImplementationB : IMixinInterfaceB 
{ 
    public void MethodB(int parameter) 
    { 
     Console.WriteLine("IMixinInterfaceB.MethodB({0})", parameter); 
    } 
} 

그런 다음 당신은 믹스 인을 생성하는 유형을 병합 할 수 있습니다 : 모양이 예제를 가지고

var config = MixinConfiguration.BuildFromActive() 
      .ForClass<TargetImplementation>() 
      .AddMixin<MixinImplementationA>() 
      .AddMixin<MixinImplementationB>() 
      .BuildConfiguration(); 
MixinConfiguration.SetActiveConfiguration(config); 

불행하게도, 당신은 단순히 TargetImplementation에 새를 호출 할 수 있으며, 믹스 인을 기대합니다. 대신 Re-mix에 TargetImplementation 인스턴스를 작성하여 사용자 지정 사항에 대한 새 유형을 작성하고 인스턴스화 할 수 있도록 요청해야합니다. TargetImplementation의 인스턴스를 요청하면 결합 된 모든 인터페이스와 클래스가 포함 된 mixin을 반환합니다.

ITargetInterface target = ObjectFactory.Create<TargetImplementation>(ParamList.Empty); 

target.DoSomething(); 

var targetAsMixinA = target as IMixinInterfaceA; 
if (targetAsMixinA != null) 
{ 
    targetAsMixinA.MethodA(); 
} 

var targetAsMixinB = target as IMixinInterfaceB; 
if (targetAsMixinB != null) 
{ 
    targetAsMixinB.MethodB(30); 
} 
관련 문제