克隆类定义(PCL)

时间:2016-10-01 16:24:50

标签: c# reflection portable-class-library redefinition

问题: 是否可以使用反射克隆类定义?我不是在谈论浅层克隆,也不是深度克隆。我在谈论定义克隆。我希望有一个类,所有实例之间不共享静态变量,而只是我创建的定义。而我(或库)需要能够在以后从这个类创建一个实例。

问题: 你知道,由于以下情况,我需要这个,

有这个库希望我为它提供一个具有某种静态方法的类型。但是在我的情况下,这个静态方法需要比较另一个类型的非静态字段中的两个值。这使得无法将具有信息的实例传递给类,因为它尚未初始化。查看以下情况示例:

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正常工作,我需要首先访问StaticClass的{​​{1}}类的实例。并且我不能使SOMELIBRARY静态,因为每次都有多个此类实例处于活动状态。

我能想到的唯一方法是重新定义一个新的MasterClass,其中一个静态字段指向定义它的StaticClass(或克隆定义)。然而,我对反思的了解使我无法这样做。所以我在这里问这甚至可能吗?而且我真的希望能够在PCL配置文件下完成它。

真实世界: 仅为了解更多信息,我实际上是在讨论MasterClassXAMARIN.iOS类,特别是NSUrlProtocol方法。

可能的解决方案:通过更多的思考,我发现解决此问题的另一种方法是使CanInitWithRequest通用;这样做允许我根据StaticClass定义获得静态变量。但是,要实现此功能,我需要能够在运行时创建唯一且可能为空的类型。这可能吗?

XAMARIN.iOS:不幸的是,在iOS上没有Reflection.Emit可用,所以现在我不相信这甚至可以实现。还在等待你对这种情况的评论。

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

2 个答案:

答案 0 :(得分:2)

有许多方法可以在运行时创建一个类,这看起来就像你要问的那样。您的问题似乎排除了package intersection func String(a []string, b []string) (inter []string) func Int(a []int, b []int) (inter []int) func Float64(a []Float64, b []Float64) (inter []Float64) ,因此您可能需要探索some of the other answers on this topic以查看它们是否适合您的平台(Xamarin.IOS)。

那就是说,你的问题似乎表明你的实现中有代码味道。您正在尝试在API注册函数中映射类实例,该函数依赖于静态方法来指示资源是否适合处理某种类型的请求(System.Reflection.Emit)。此函数应仅指示已注册的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映射到masterAHandler1映射到masterB,依此类推。

答案 1 :(得分:0)

经过大量搜索,我发现在Xamarin.iOS下无法在C#中创建一个空类型,因此我不得不更改我的代码以符合Apple API的期望。

就我而言,我最终保留了MasterClass中要使用的StaticClass所有实例的列表;构造函数和静态方法都在列表中,并将所需的MasterClass与请求匹配。这里存在风险,因此这样做会导致内存泄漏,因为MasterClass的实例永远不会被收集,但在我的情况下,这不是一个问题。