2016-10-01 70 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爲靜態,因爲這個類的每個實例都有多個活動。

我唯一能想到的方式是用一個指向MasterClass的靜態字段重新定義新的StaticClass,該字段定義了它(或克隆了定義)。然而,我的反思知識卻讓我無法做到這一點。所以在這裏我問這甚至可能嗎?我真的希望能夠在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的期望。

在我的情況下,我最終保留了MasterClass的所有實例的列表,用於StaticClass;構造函數和靜態方法都會遍歷該列表,並將所需的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 
    } 
} 

這種模式可以幫助你建立你想在運行時通過類的創建,實現組件之間的關係。這種模式將允許您調用不同類型的處理程序(即NSURLProtocol類)訪問不同的Master實例。在此示例中,masterA映射到Handler1masterBHandler2,依此類推。

+0

[Sorry for poor english]謝謝你的回答,但在這種情況下,Handlers類必須在設計時定義。我正在尋找可以在運行時創建的解決方案。我清楚了嗎? –

+0

感謝您的回答,經過很長時間:),不幸的是,似乎沒有辦法在運行時用XAMARIN.iOS定義類。即使這似乎是一種代碼味道,但這更多的是在縮進功能方面的不兼容性。 Apple設計了API來通過靜態請求處理程序處理請求,但是,我的實現需要基於實例的檢查。不幸的是,在你的例子中,你遵循了與Apple相同的方式,並事先定義了類。我不知道我可能需要多少班,一,二或一百。所以我無法在代碼中定義它們。 –