わかりました、Vikasの問題のフレーミングが明確になったため、私は自分の質問の答えを完成させました。そして解決策は、このタイプの問題に対する標準的な PCL アプローチです: インターフェイスを作成し、コンテナーを構成し、DI を使用します。
この場合、PCLで、次のようにプロパティとして使用する 2 つの設定を持つ 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; }
}
注: 簡単にインターフェイスをスキップして、このヘルパー クラスを単独で使用することもできますが、コンテナーを扱うときはインターフェイスを使用するのが好きです。
次に、Newtonsoft シリアライザーが存在するPCLで、シリアル化メソッド内で設定を直接作成するのではなく、コンテナーから設定を使用します。先に進み、そのコードもここに含めます (この問題のためにシリアル化をインターフェイスに抽象化したので、実装を交換できます)。
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);
}
/// <summary>
/// This is used to overcome the problem of PCL vs non-PCL versions when using TypeNameAssemblyFormat.
/// see http://stackoverflow.com/questions/27080363/missingmethodexception-with-newtonsoft-json-when-using-typenameassemblyformat-wi
/// </summary>
/// <returns></returns>
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 を消費するSystem.Runtime.Serialization.Formatters.FormatterAssemblyStyle
(PCL で動作する可能性がありますが、Xamarin には問題があります - 以下を参照してください) で、Vikas の回答で説明されているように、コンテナーを適切に構成します。
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
};
//hack: FormatterAssemblyStyle exists in two dlls and extern alias doesn't work in xamarin studio
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,
//TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full //set using dynamic
};
dynamic dynSettings = concreteNewtonsoftSettings;
dynSettings.TypeNameAssemblyFormat = enumInstance;
commonGib.Serialization.NewtonsoftJsonSettingsProvider.CreateAndRegisterWithContainerIdem(defaultNewtonsoftSettings, concreteNewtonsoftSettings);
commonGib.Serialization.NewtonsoftJsonSerializer.RegisterAsSerializerInContainer();
}