2016-10-01 2 views
3

질문 : 리플렉션을 사용하여 클래스 정의를 복제 할 수 있습니까? 나는 얕은 복제 나 깊은 복제에 대해서 말하고있는 것이 아닙니다. 정의 복제에 대해 이야기하고 있습니다. 모든 인스턴스간에 공유되지 않는 정적 변수를 가진 클래스가 필요하지만, 내가 만든 정의 만 갖고 싶습니다. 그리고 나 (또는 ​​도서관)는 나중에이 클래스에서 인스턴스를 생성 할 수 있어야합니다.클라스 정의 (PCL)

문제점 : 당신이 볼 , 나는

나 종류가 특정 정적 메소드를 갖는를 제공 할 것으로 예상이 라이브러리가 있기 때문에 다음과 같은 시나리오의이 필요합니다. 그러나 내 경우에는이 정적 메서드는 다른 형식의 정적 필드가 아닌 두 값을 비교해야합니다. 따라서 아직 초기화되지 않았으므로 클래스에 정보가있는 인스턴스를 전달할 수 없습니다. 상황을 다음 예를 체크 아웃 :

class MasterClass 
{ 
    public int SomeInfo {get; set;} = 10; 
    public void PeresentClass() 
    { 
     SOMELIBRARY.RegisterType(typeof(StaticClass)); 
    } 
} 
class StaticClass 
{ 
    public static bool CanCreate(int someVar) 
    { 
     // I need to compare someVar with the SomeInfo property of MasterClass instance that presented this type to the SOMELIBRARY. 
    } 
    public StaticClass() 
    { 
     // Something irrelevant 
    } 
} 

을 나는 SOMELIBRARY를 통제하고이 코드를 작성하기로 결정 방법이 없습니다 위의 예에서. 그러나 어떤 사람들은 CanCreate 메서드를 먼저 호출 한 다음 요구 사항을 충족하는 경우 클래스의 인스턴스를 만드는 방법을 사용하는 것으로 보입니다.

그러나 CanCreate은 올바르게 작동하려면 클래스의 인스턴스에 액세스해야합니다. StaticClassSOMELIBRARY에 첫 번째로 입력해야합니다. 그리고 때마다 활성화되는이 클래스의 인스턴스가 두 개 이상 있기 때문에 MasterClass을 정적으로 만들 수 없습니다.

내가 생각할 수있는 유일한 방법은 새 필드 StaticClass을 정의한 MasterClass을 가리키는 정적 필드로 다시 정의하는 것이 었습니다. 정의를 복제했습니다. 그러나 반영에 대한 나의 지식은 아직 그렇게하지 못했습니다. 그래서 여기에 나는 이것이 가능하다는 것을 묻고있다. 그리고 저는 PCL 프로파일 하에서 그것을 할 수 있기를 정말로 원합니다.

현실 세계 : 그냥 자세한 내용은, 실제로 약 XAMARIN.iOSNSUrlProtocol 클래스, 특별히 CanInitWithRequest 방법을 이야기하고있다.

가능한 해결책 : 더 많은 생각을하면이 문제를 해결할 수있는 다른 방법은 StaticClass을 일반화하는 것입니다. 이렇게하면 type 정의 당 정적 변수를 가질 수 있습니다. 그러나 이것이 작동하려면 런타임에 고유하고 가능한 빈 유형을 생성 할 수 있어야합니다. 이것이 가능한가?

XAMARIN.iOS : 불행히도 Reflection.Emit은 iOS에서 사용할 수 없으므로 지금까지는 어떤 식 으로든 이것이 가능하다고 생각하지 않습니다. 아직 상황에 대한 의견을 기다리고 있습니다.

https://developer.xamarin.com/guides/ios/advanced_topics/limitations/#System.Reflection.Emit

+0

정확히 어떤 SOMELIBRARY가 StaticClass와 정확히 일치합니까? – Evk

+0

@Evk : 클래스의 새로운 인스턴스를 생성하기 전에 CanCreate 메소드를 호출하여 클래스가 특정 상황을 처리 할 수 ​​있는지 확인합니다. –

+0

CanCreate가 정적 메서드 인 이유는 무엇입니까? 그것이 일부 도서관의 요구 사항입니까? – Evk

답변

0

많은 검색을 한 후에 Xamarin.iOS에서 C#으로 빈 형식을 만들 수있는 방법을 찾지 못했습니다. 결과적으로 Apple API의 기대에 맞게 코드를 변경해야했습니다.

필자의 경우 StaticClass에서 사용할 MasterClass의 모든 인스턴스 목록을 유지했다. 생성자와 정적 메서드는 모두 목록을 뒤지고 원하는대로 MasterClass과 일치시킵니다. MasterClass의 인스턴스가 수집되지 않기 때문에 메모리 누수가 발생하는 위험이 있습니다. 그러나 제 경우에는 이것이 걱정되지 않습니다.

2

당신이 요구하는 것처럼 보인다 런타임에 클래스를 생성하는 방법은 여러 가지가 있습니다. 귀하의 질문은 System.Reflection.Emit을 배제한 것으로 보이므로 some of the other answers on this topic을 탐색하여 해당 플랫폼 (Xamarin.IOS)에 맞는지 확인하십시오.

귀하의 질문은 귀하의 구현에서 코드 냄새를 나타내는 것으로 보입니다.API 등록 함수에서 클래스 인스턴스를 매핑하려고합니다. 정적 메서드를 사용하여 요청 유형을 처리 할 때 리소스의 적합성을 나타냅니다 (canInitWithRequest). 이 함수는 등록 된 NSURLProtocol 클래스가 특정 요청 유형을 처리 할 수 ​​있는지 나타내는 경우에만 표시되어야하며 시스템의 다른 객체의 일부 클래스 속성에 종속되어서는 안됩니다.

NSURLProtocol 인스턴스가 기본 프레임 워크에서 호출 될 때 런타임에 공유 리소스를 조회하는 것이 더 나은 방법 일 수 있습니다. 다음과 같은 예를 들어, 뭔가 :이 패턴은 당신이 런타임에 클래스 생성을 통해 달성하려고하는 구성 요소 간의 관계를 설정하는 데 도움이 될

static class SystemMap { 
    // Store some mapping information in a commonly accessible system resource 
    // In this case a simple static class that wraps up a dictionary 
    static Dictionary<Type, Master> systemMap = new Dictionary<Type, Master>(); 

    // Allow registered components to be accessed 
    public static Master getRegisteredMaster(Type handlerType) { 
     return systemMap[handlerType]; 
    } 

    // Allow new registrations to be made in your system 
    public static void registerNewMaster(Master registrant, Type handlerType) { 
     systemMap[handlerType] = registrant; 
    } 
} 

class Master { 
    // This would be your custom class that you instantiate throughout your system 
    public string name; 
    public int someVar { get; set; } = new Random().Next(1, 100); 
    public Master(string name) { 
     this.name = name; 
    } 
} 

class BaseHandlerType { 
    // This would be NSURLProtocol 
} 

class Handler1 : BaseHandlerType { 
    // This would be canInitWithRequest 
    public static bool CanCreate(int someVar) { 
     Master myMaster = SystemMap.getRegisteredMaster(typeof(Handler1)); 
     return someVar > myMaster.someVar; 
    } 
} 

class Handler2 : BaseHandlerType { 
    //... Register various handler types to various "Master" instances in your system 
    // This is a concrete implementation of NSURLProtocol 
} 

class Handler3 : BaseHandlerType { 
    //... Register various handler types to various "Master" instances in your system 
    // This is a concrete implementation of NSURLProtocol 
} 

class SystemFactory { 
    // Use a factory method to instantiate the system components and plug things together 
    public void initializeSystem() { 
     var masterA = new Master("a"); 
     var masterB = new Master("b"); 
     var masterC = new Master("c"); 
     SystemMap.registerNewMaster(masterA, typeof(Handler1)); 
     SystemMap.registerNewMaster(masterB, typeof(Handler2)); 
     SystemMap.registerNewMaster(masterC, typeof(Handler3)); 
     SomeLibrary.register(typeof(Handler1)); 
     SomeLibrary.register(typeof(Handler2)); 
     SomeLibrary.register(typeof(Handler3)); 
    } 
} 

static class SomeLibrary { 
    public static void register(Type handlerType) { 
     // This represents the API registration 
    } 
} 

. 이 패턴을 사용하면 다양한 Master 인스턴스가 호출 될 때 다양한 유형의 핸들러 (예 : NSURLProtocol 클래스)가 다른 인스턴스에 액세스 할 수 있습니다. 이 예에서 masterAHandler1, masterB에서 Handler2 등으로 매핑됩니다.

+0

[영어 불쌍히 드려 죄송합니다.] 답변 주셔서 감사합니다.하지만이 경우 처리기 클래스는 디자인 타임에 정의해야합니다. 나는 실행 시간에 만들 수있는 솔루션을 찾고있었습니다. 나는 충분히 명확하게 갔다? –

+0

답변을 주셔서 감사합니다. 오랜 시간이 지난 후에 :), 불행히도 XAMARIN.iOS를 사용하여 런타임에 클래스를 정의 할 수있는 방법이없는 것 같습니다. 심지어 코드 냄새 같은 것 같지만, 이것은 들여 쓰기 된 기능에 더 많은 비 호환성이 있습니다. Apple은 정적 요청 처리기를 통해 요청을 처리하도록 API를 설계했지만 구현시 인스턴스 기반 검사가 필요했습니다. 불행히도, 당신의 예에서, 당신은 Apple과 같은 방식으로 따라 왔고 미리 클래스를 정의했습니다. 나는 얼마나 많은 계급이 필요할지 모른다. 하나, 둘, 또는 백. 따라서 코드에서 정의 할 수는 없습니다. –