2016-10-01 65 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相同的方式,并事先定义了类。我不知道我可能需要多少班,一,二或一百。所以我无法在代码中定义它们。 –