好的,由于Vikas对问题的清晰表述,我最终完成了自己的问题答案。解决方案是使用标准的PCL方法:创建接口、配置容器、使用DI。
在这种情况下,在我的PCL中,我创建了一个INewtonsoftJsonSettingsProvider接口,其中包含我用作属性的两个设置,如下所示:
public interface INewtonsoftJsonSettingsProvider
{
JsonSerializerSettings Default { get; set; }
JsonSerializerSettings Concrete { get; set; }
}
然后,在我的PCL中,我创建了如下的这个类的具体实现:
public class NewtonsoftJsonSettingsProvider : Interfaces.INewtonsoftJsonSettingsProvider
{
public JsonSerializerSettings Default { get; set; }
public JsonSerializerSettings Concrete { get; set; }
}
注意:我可以轻松地跳过界面,只使用这个辅助类,但在处理容器时我喜欢使用接口。接下来,在我的PCL中,我的Newtonsoft序列化程序存在,我使用容器中的设置来消耗它们,而不是直接在序列化方法中创建那些设置。我将在此处包含该代码(我因此问题而将序列化抽象为一个接口,以便我可以交换实现)。
public class NewtonsoftJsonSerializer : ICustomSerializer
{
public static void RegisterAsSerializerInContainer()
{
var key = Resx.DIKeys.DefaultSerializer;
var typeContract = typeof(ICustomSerializer);
if (DI.Ton.KeyExists(key))
{
var instance = DI.Ton.Get(typeContract, key);
DI.Ton.RemoveInstance(key, instance, typeContract);
}
DI.Ton.AddImplementationType(typeof(ICustomSerializer),
typeof(NewtonsoftJsonSerializer),
isShared: true);
var serializer = new NewtonsoftJsonSerializer();
DI.Ton.AddInstance<ICustomSerializer>(Resx.DIKeys.DefaultSerializer, serializer);
}
private static INewtonsoftJsonSettingsProvider GetSettingsProvider()
{
var key = typeof(INewtonsoftJsonSettingsProvider).Name;
var settings = DI.Ton.GetInstance<INewtonsoftJsonSettingsProvider>(key);
return settings;
}
public byte[] SerializeToBytes(object obj)
{
var settings = GetSettingsProvider();
var json = JsonConvert.SerializeObject(obj, settings.Default);
var jsonBytes = Encoding.UTF8.GetBytes(json);
return jsonBytes;
}
public T DeserializeFromBytes<T>(byte[] serializedBytes)
{
var json = Encoding.UTF8.GetString(serializedBytes, 0, serializedBytes.Length);
var settings = GetSettingsProvider();
var obj = JsonConvert.DeserializeObject<T>(json, settings.Default);
return obj;
}
public byte[] SerializeToBytes_UseConcreteTypes(object obj)
{
var settings = GetSettingsProvider();
var json = JsonConvert.SerializeObject(obj, settings.Concrete);
var jsonBytes = Encoding.UTF8.GetBytes(json);
return jsonBytes;
}
public T DeserializeFromBytes_UseConcreteTypes<T>(byte[] serializedBytes)
{
var json = Encoding.UTF8.GetString(serializedBytes, 0, serializedBytes.Length);
var settings = GetSettingsProvider();
var obj = JsonConvert.DeserializeObject<T>(json, settings.Concrete);
return obj;
}
}
接下来,在我使用非PCL和非Xamarin的情况下(可能在PCL中可以工作,但Xamarin有问题 - 请参见下文),我按照Vikas的答案所述,使用正确的System.Runtime.Serialization.Formatters.FormatterAssemblyStyle
配置容器:
private static void UseNewtonsoft()
{
var defaultNewtonsoftSettings = new Newtonsoft.Json.JsonSerializerSettings()
{
Formatting = Newtonsoft.Json.Formatting.Indented
};
var concreteNewtonsoftSettings = new Newtonsoft.Json.JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects,
Formatting = Formatting.Indented,
TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full
};
Serialization.NewtonsoftJsonSettingsProvider.CreateAndRegisterWithContainerIdem(defaultNewtonsoftSettings, concreteNewtonsoftSettings);
Serialization.NewtonsoftJsonSerializer.RegisterAsSerializerInContainer();
}
这在我的.Net测试项目中可以顺利执行。然而,当我在Xamarin.Android项目中使用时,出现了错误,指出FormatterAssemblyStyle同时存在于Newtonsoft和MonoAndroid mscorlib中。由于Xamarin Studio似乎不支持extern别名,因此我使用了反射和动态方法,如下所示:
void UseNewtonsoft()
{
var defaultNewtonsoftSettings = new Newtonsoft.Json.JsonSerializerSettings()
{
Formatting = Newtonsoft.Json.Formatting.Indented
};
var assmNewtonsoft = System.Reflection.Assembly.GetAssembly(typeof(Newtonsoft.Json.ConstructorHandling));
var enumType = assmNewtonsoft.GetType("System.Runtime.Serialization.Formatters.FormatterAssemblyStyle");
dynamic enumInstance = Enum.Parse(enumType, "Full");
var concreteNewtonsoftSettings = new Newtonsoft.Json.JsonSerializerSettings()
{
TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects,
Formatting = Newtonsoft.Json.Formatting.Indented,
};
dynamic dynSettings = concreteNewtonsoftSettings;
dynSettings.TypeNameAssemblyFormat = enumInstance;
commonGib.Serialization.NewtonsoftJsonSettingsProvider.CreateAndRegisterWithContainerIdem(defaultNewtonsoftSettings, concreteNewtonsoftSettings);
commonGib.Serialization.NewtonsoftJsonSerializer.RegisterAsSerializerInContainer();
}
Newtonsoft.Json
只是从第一个使用它的 PCL 引用吗?还是有其他非-PCL 程序集(或者甚至具有不同配置文件的 PCL 程序集)也引用了Newtonsoft.Json
?换句话说,当这段代码不起作用时,有哪些程序集引用了Newtonsoft.Json
,它们的配置文件是什么?相反,当它起作用时,Newtonsoft.Json
是否只从一个包含上述代码的 PCL 程序集中引用? - Vikas Gupta