static void VerifyMember(Type resolverType, EmittableMemberInfo info) { var formatter = typeof(Formatter <,>).MakeGenericType(resolverType, info.MemberType).GetTypeInfo().GetProperty("Default").GetValue(null, null); var error = formatter as IErrorFormatter; if (error != null) { throw error.GetException(); } // OK, Can Serialzie. }
public static Tuple <int, EmittableMemberInfo>[] GetMembers(Type resolverType, Type type, bool isClass) { if (isClass) { if (!type.GetTypeInfo().IsClass) { throw new InvalidOperationException("Type must be class. " + type.Name); } } else { if (!type.GetTypeInfo().IsValueType) { throw new InvalidOperationException("Type must be class. " + type.Name); } } if (type.GetTypeInfo().GetCustomAttributes(typeof(ZeroFormattableAttribute), true).FirstOrDefault() == null) { throw new InvalidOperationException("Type must be marked with ZeroFormattableAttribute. " + type.Name); } if (isClass) { if (!type.GetTypeInfo().GetConstructors().Any(x => x.GetParameters().Length == 0)) { throw new InvalidOperationException("Type must needs parameterless constructor. " + type.Name); } } var dict = new Dictionary <int, EmittableMemberInfo>(); foreach (var item in type.GetTypeInfo().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (item.GetCustomAttributes(typeof(IgnoreFormatAttribute), true).Any()) { continue; } // If base property type marked UnionKey, okay. var foundUnionKey = false; var propInfo = item; do { if (propInfo.GetCustomAttributes(typeof(UnionKeyAttribute), true).Any()) { foundUnionKey = true; break; } propInfo = null; var baseType = item.DeclaringType.GetTypeInfo().BaseType; if (baseType != null) { var basePropInfo = baseType.GetTypeInfo().GetProperty(item.Name); if (basePropInfo != null) { propInfo = basePropInfo; } } } while (propInfo != null); if (foundUnionKey) { continue; } var index = item.GetCustomAttributes(typeof(IndexAttribute), true).Cast <IndexAttribute>().FirstOrDefault(); if (index == null) { throw new InvalidOperationException("Public property must be marked with IndexAttribute or IgnoreFormatAttribute. " + type.Name + "." + item.Name); } var getMethod = item.GetGetMethod(true); var setMethod = item.GetSetMethod(true); if (isClass) { if (getMethod == null || setMethod == null || getMethod.IsPrivate || setMethod.IsPrivate) { throw new InvalidOperationException("Public property must needs both public/protected get and set accessor." + type.Name + "." + item.Name); } } if (isClass) { if (!getMethod.IsVirtual || !setMethod.IsVirtual) { throw new InvalidOperationException("Public property's accessor must be virtual. " + type.Name + "." + item.Name); } } if (dict.ContainsKey(index.Index)) { throw new InvalidOperationException("IndexAttribute is not allow duplicate number. " + type.Name + "." + item.Name + ", Index:" + index.Index); } var info = new EmittableMemberInfo(item); VerifyMember(resolverType, info); dict[index.Index] = info; } foreach (var item in type.GetTypeInfo().GetFields(BindingFlags.Public | BindingFlags.Instance)) { if (item.GetCustomAttributes(typeof(IgnoreFormatAttribute), true).Any()) { continue; } var index = item.GetCustomAttributes(typeof(IndexAttribute), true).Cast <IndexAttribute>().FirstOrDefault(); if (index == null) { throw new InvalidOperationException("Public field must mark IndexAttribute or IgnoreFormatAttribute. " + type.Name + "." + item.Name); } else if (isClass) { throw new InvalidOperationException("Class does not allow that field marks IndexAttribute. " + type.Name + "." + item.Name); } if (dict.ContainsKey(index.Index)) { throw new InvalidOperationException("IndexAttribute is not allow duplicate number. " + type.Name + "." + item.Name + ", Index:" + index.Index); } var info = new EmittableMemberInfo(item); VerifyMember(resolverType, info); dict[index.Index] = info; } return(dict.OrderBy(x => x.Key).Select(x => Tuple.Create(x.Key, x.Value)).ToArray()); }