private static TypeActivator ClassActivator(Type expectedType) { var constructors = expectedType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) .Where(c => c.IsDefined(typeof(ConstructorAttribute), true)) .ToList(); if (constructors.Count == 0) { throw new DeserializationException( $"No constructors found for {expectedType} found with AiWen.Db.Constructor attribute"); } if (constructors.Count > 1) { throw new DeserializationException( $"More than one constructor found for {expectedType} found with AiWen.Db/Constructor attribute"); } var constructor = constructors[0]; var parameters = constructor.GetParameters(); var paramNameTypes = new Dictionary <byte[], ParameterInfo>(new ByteArrayEqualityComparer()); var injectables = new Dictionary <string, ParameterInfo>(); var networkParams = new List <ParameterInfo>(); var alwaysCreated = new List <ParameterInfo>(); foreach (var param in parameters) { var injectableAttribute = param.GetCustomAttributes <InjectAttribute>().FirstOrDefault(); if (injectableAttribute != null) { injectables.Add(injectableAttribute.ParameterName, param); } var networkAttribute = param.GetCustomAttributes <NetworkAttribute>().FirstOrDefault(); if (networkAttribute != null) { networkParams.Add(param); } var paramAttribute = param.GetCustomAttributes <ParameterAttribute>().FirstOrDefault(); string name; if (paramAttribute != null) { name = paramAttribute.ParameterName; if (paramAttribute.AlwaysCreate) { alwaysCreated.Add(param); } } else { name = param.Name; } paramNameTypes.Add(Encoding.UTF8.GetBytes(name), param); } var activator = ReflectionUtil.CreateActivator(constructor); var clsConstructor = new TypeActivator(activator, paramNameTypes, injectables, networkParams, alwaysCreated); return(clsConstructor); }
private static void SetNetwork(TypeActivator constructor, object?[] parameters, Network?network) { foreach (var item in constructor.NetworkParameters) { // We don't check that we have a non-null network as we want to // allow enumeration to use the same models as normal lookups. We // cannot support the network field for enumeration as the objects // are cached. parameters[item.Position] = network; } }
private static void SetInjectables(TypeActivator constructor, object[] parameters, InjectableValues?injectables) { foreach (var item in constructor.InjectableParameters) { if (injectables == null || !injectables.Values.ContainsKey(item.Key)) { throw new DeserializationException($"No injectable value found for {item.Key}"); } parameters[item.Value.Position] = injectables.Values[item.Key]; } }
private void SetAlwaysCreatedParams( TypeActivator constructor, object[] parameters, InjectableValues?injectables, Network?network ) { foreach (var param in constructor.AlwaysCreatedParameters) { if (parameters[param.Position] != null) { continue; } var activator = _typeAcivatorCreator.GetActivator(param.ParameterType); var cstorParams = activator.DefaultParameters(); SetInjectables(activator, cstorParams, injectables); SetNetwork(activator, cstorParams, network); SetAlwaysCreatedParams(activator, cstorParams, injectables, network); parameters[param.Position] = activator.Activator(cstorParams); } }