2017-10-01 11 views
0

나는 기본 클래스 및 인터페이스, 예를 구현하는 몇 가지 파생 클래스가있는 경우 :C# : 클래스를 런타임에 구현하지만 시간을 컴파일하지 않는 인터페이스로 캐스팅하는 방법이 있습니까?

public class BaseClass 
{ 

} 

public interface IInterface 
{ 
    void SomeMethod(); 
} 

public class DerivedA : BaseClass, IInterface 
{ 
    public void SomeMethod() 
    { 
     // some implementation 
    } 
} 
public class DerivedB: BaseClass, IInterface 
{ 
    public void SomeMethod() 
    { 
     // some other implementation 
    } 
} 

을 그리고 나는 BaseClass로 필드가 관련이없는 클래스가 있습니다

public class UnrelatedClass 
{ 
    public BaseClass foo; 
} 

내 구현은 가정 제공을 foo 인터페이스를 구현하는 일부 파생 된 클래스가 있어야합니다 (하지만 난 그냥 그래서 그 클래스에 캐스팅 할 수 없습니다) 어떻게 든 IInterface 캐스팅 할 수 및 컴파일 오류를 생성하지 않고 foo.SomeMethod() 호출 할 수 있습니다. ?

PS-이 작업을 수행하는 데 정말로 둥근 방법이며 대신 "IInterface foo"필드를 사용해야하지만 Unity가 인터페이스 필드를 직렬화하지 않고 사용자 정의 관리자를 쓰지 않으려 고합니다. 노력하고있어.

+0

는'BaseClass'가'SomeMethod'이 나던 : BaseClassIInterface를 구현하고 파생 클래스가 재정의 할 필요가있어서, 여기에 제안 된 디자인이다. 'IInterface'는 그것을 가지고 있습니다. 그래서'SomeMethod'를'BaseClass' 안에 넣지 않는 이유는 무엇입니까? '추상적'? – FCin

+0

왜'BaseClass'는'IInterface'를 구현하지 않습니까? –

+1

'is' 키워드를 사용하여 다음을 확인하십시오 :'if (foo is IInterface) {...}' – CodingYoshi

답변

4

반사 방식 (천천히!)으로 인터페이스 방법에 액세스하거나 as 연산자로 '안전 -전송'할 수 있습니다. 캐스트가 실패하면 as 연산자는 null을 반환합니다. 이와 같이 :

var impl = foo as IInterface; 
impl?.SomeMethod() 
// or if(impl != null) impl.SomeMethod(); 
+0

니스! 잠시 동안이 질문을 잊어 버렸지 만, 이것이 내가 찾고 있었던 것이었다. 나는 당신이 컴파일 타임에 컨버터블이 아닌 타입으로 "as"를 사용할 수 있다는 것을 몰랐다. 감사합니다 :) – user2944295

0

디자인을 변경하여 해결책을 제공 할 것입니다. 궁극적 인 목표는 foo 개체가 BaseClassIInterface의 모든 구성원을 갖기를 바랍니다. 당신과 같이 추상 클래스를 만들 수 있습니다

abstract class BaseClassAndInterface: BaseClass, IInterface { 
    public abstract void SomeMethod(); 
} 

지금 BaseClassAndInterface에서 DerivedADerivedB 상속을하고 인터페이스의 메소드를 구현합니다.

public class DerivedA : BaseClassAndInterface 
{ 
    public override void SomeMethod() 
    { 
     // some implementation 
    } 
} 
public class DerivedB: BaseClassAndInterface 
{ 
    public override void SomeMethod() 
    { 
     // some other implementation 
    } 
} 

이제 fooBaseClassAndInterface로 선언 할 수 있습니다.

+0

내가 생각한이 특정 예제를 위해 작동하지만, 당신이 IInterface를 구현하는 다른 기본 클래스를 사용하고 싶다면 떨어져있다. (각각의 중간에 추상 기본 클래스가 필요하기 때문에). 실제로 원래 문제 (오브젝트들 간 충돌)에 대한 다른 해결 방법을 찾았지만, 가상의 관점에서 보면 여전히 intrested입니다 : 런타임에 __does__을 구현하는 객체의 인터페이스 멤버를 사용할 수 있습니까? 컴파일 타임에 변수 __doesn't__? – user2944295

1

지금 바로 BaseClass에는 디자인에 아무런 포인트가 없습니다. 디자인을 조금만 변경하면 런타임에 검사를 수행 할 필요조차 없습니다.

public interface IInterface 
{ 
    void SomeMethod(); 
} 

public abstract class BaseClass : IInterface 
{ 
    public abstract void SomeMethod(); 
    // Or virtual with common implementation 
} 

public class DerivedA : BaseClass 
{ 
    public override void SomeMethod() 
    { 
     // some implementation 
    } 
} 
public class DerivedB : BaseClass 
{ 
    public override void SomeMethod() 
    { 
     // some other implementation 
    } 
}