void GenerateFor(TypeMetaData metaData, string property, IPropertyValidator validator) { var validatorType = validator.GetType(); var types = new List <Type>(); types.Add(validatorType); types.AddRange(validatorType.GetTypeInfo().GetInterfaces()); foreach (var type in types) { if (_generatorsByType.ContainsKey(type)) { var propertyName = property.ToCamelCase(); var rule = _generatorsByType[type].GeneratorFrom(property, validator); var ruleName = rule.GetType().Name.ToCamelCase(); metaData[propertyName][ruleName] = rule; } } }
/// <summary> /// Initializes a new instance of the <see cref="DesignTimeTypeDescriptor"/> class. /// </summary> /// <param name="objectType">Type of the object.</param> /// <param name="instance">The instance.</param> public EditableTypeDescriptor(Type objectType) { Type wrapperObjectType = objectType; Type wrappedObjectType = objectType; Type baseType = wrapperObjectType.BaseType; while (baseType != null && baseType != typeof(object)) { if (baseType.Name == typeof(EditableAdapter <>).Name && baseType.GetGenericArguments().Length > 0) { wrappedObjectType = baseType.GetGenericArguments()[0]; break; } baseType = baseType.BaseType; } _context = TypeMetaDataRepository.GetFor(wrapperObjectType, wrappedObjectType); }
/// <summary> /// Initializes the created object after its construction. /// </summary> /// <param name="obj">The object to initialize.</param> /// <param name="typeMetaData">Metadata about object to initialize</param> private void InitializeAfterConstruction(object obj, TypeMetaData typeMetaData) { if (obj == null) { return; } string objectType = ObjectToStringHelper.ToTypeString(obj); Log.Debug("Initializing type '{0}' after construction", objectType); // TODO: Consider to cache for performance var dependencyResolverManager = DependencyResolverManager.Default; var dependencyResolver = _serviceLocator.ResolveType <IDependencyResolver>(); dependencyResolverManager.RegisterDependencyResolverForInstance(obj, dependencyResolver); Log.Debug("Injecting properties into type '{0}' after construction", objectType); var type = obj.GetType(); foreach (var injectedProperty in typeMetaData.GetInjectedProperties()) { var propertyInfo = injectedProperty.Key; var injectAttribute = injectedProperty.Value; try { var dependency = _serviceLocator.ResolveType(injectAttribute.Type, injectAttribute.Tag); propertyInfo.SetValue(obj, dependency, null); } catch (Exception ex) { throw Log.ErrorAndCreateException <InvalidOperationException>(ex, "Failed to set property '{0}.{1}' during property dependency injection", type.Name, propertyInfo.Name); } } var objAsINeedCustomInitialization = obj as INeedCustomInitialization; if (objAsINeedCustomInitialization != null) { objAsINeedCustomInitialization.Initialize(); } }
/// <summary> /// Gets the constructors metadata. /// </summary> /// <param name="type">The type.</param> /// <returns>The <see cref="TypeMetaData"/>.</returns> private TypeMetaData GetTypeMetaData(Type type) { return(_typeConstructorsMetadataLock.PerformUpgradableRead(() => { if (_typeConstructorsMetadata.TryGetValue(type, out var result)) { return result; } result = new TypeMetaData(type); _typeConstructorsMetadataLock.PerformWrite(() => { _typeConstructorsMetadata.Add(type, result); }); return result; })); }
public void TestMetaDataSerialization() { var metaData = new TypeMetaData(); metaData.StoreFieldNumber("blah/", "myName", "someField", 2); var serializer = ObjectBuilder.GetSerializer(); var result = serializer.Serialize(metaData, AppModeType); Assert.IsTrue(result.Data.Length > 0, "Meta data was not successfully serialized. The resultant byte count was zero."); var deserialized = serializer.Deserialize <TypeMetaData>(result.Data, AppModeType); Assert.IsNotNull(deserialized, "Deserialization was not succesfull, the resultant object was null."); int?fieldNumber; var success = deserialized.GetFieldNumber("blah/", "myName", "someField", out fieldNumber); Assert.IsTrue(success, "The expected field number was not found in the deserialized data. MetaData deserialization failed."); Assert.AreEqual(2, fieldNumber.Value, "The expected field number was not found in the deserialized data. MetaData deserialization failed."); }
void GenerateForChildValidator(TypeMetaData metaData, Type[] genericArguments, IGrouping <string, IPropertyValidator> member, IPropertyValidator validator, bool isModelRule, string currentKey) { var isConcept = false; if (genericArguments.Length == 1) { // TODO: This is probably needed because of a bug in FluentValidation. // At least it seems like that. It seems there is some static cached state. // It works fine in isolated tests - but running the whole battery // makes this fail if we take out the "Value" name forcing var memberKey = member.Key; if (memberKey == string.Empty) { memberKey = "Value"; } var type = isModelRule ? genericArguments[0] : GetPropertyInfo(genericArguments[0], memberKey).PropertyType; isConcept = type.IsConcept(); } var propertyValidatorContext = new PropertyValidatorContext(new ValidationContext(null), null, null); var childValidator = (validator as ChildValidatorAdaptor).GetValidator(propertyValidatorContext); GenerateForValidator(childValidator, metaData, currentKey, isConcept, isModelRule); }
private NetworkObject CreateNetworkObject(NetworkObjectList objectList, TypeMetaData metaData, in ObjectHandle objectHandle)
void ISchemaTaintedFormatter.OnSchemaChanged(TypeMetaData meta) => ActivateSchema(meta.CurrentSchema);
internal SerializationResult(byte[] data, TypeMetaData metaData) { Data = data; MetaData = metaData; }
IFormatter GetSpecificFormatter(Type type, TypeMetaData meta) { // 1.) Cache if (meta.SpecificFormatter != null) { return(meta.SpecificFormatter); } // Sanity checks if (type.IsAbstract || type.IsInterface || type.ContainsGenericParameters) { throw new InvalidOperationException("You cannot get a formatter for abstract, interface, and open generic types because they are not "); } // 2.) TypeConfig - Custom Formatter, Custom Resolver if (meta.TypeConfig.CustomFormatter != null) { meta.SpecificFormatter = meta.TypeConfig.CustomFormatter; FormatterHelper.ThrowOnMismatch(meta.SpecificFormatter, type); InjectDependencies(meta.SpecificFormatter); return(meta.SpecificFormatter); } if (meta.TypeConfig.CustomResolver != null) { var formatter = meta.TypeConfig.CustomResolver(this, type); meta.SpecificFormatter = formatter ?? throw new InvalidOperationException($"The custom formatter-resolver registered for Type '{type.FullName}' has returned 'null'."); FormatterHelper.ThrowOnMismatch(meta.SpecificFormatter, type); InjectDependencies(meta.SpecificFormatter); return(meta.SpecificFormatter); } // 3.) User for (int i = 0; i < _userResolvers.Length; i++) { var formatter = _userResolvers[i](this, type); if (formatter != null) { meta.SpecificFormatter = formatter; FormatterHelper.ThrowOnMismatch(meta.SpecificFormatter, type); InjectDependencies(formatter); return(formatter); } } // 4.) Depending on the VersionTolerance we use different formatters if (Config.VersionTolerance.Mode != VersionToleranceMode.Disabled) { if (!meta.IsFrameworkType) { // Create SchemaFormatter, it will automatically adjust itself to the schema when it's read var formatterType = typeof(SchemaDynamicFormatter <>).MakeGenericType(type); var schemaFormatter = (IFormatter)Activator.CreateInstance(formatterType, args: new object[] { this, meta.PrimarySchema }); meta.SpecificFormatter = schemaFormatter; return(schemaFormatter); } } // 5.) Built-in for (int i = 0; i < _resolvers.Count; i++) { var formatter = _resolvers[i].GetFormatter(type); if (formatter != null) { meta.SpecificFormatter = formatter; InjectDependencies(formatter); return(formatter); } } // 6.) Dynamic { var formatter = _dynamicResolver.GetFormatter(type); if (formatter != null) { meta.SpecificFormatter = formatter; InjectDependencies(formatter); return(formatter); } } throw new NotSupportedException($"Ceras could not find any IFormatter<T> for the type '{type.FullName}'. Maybe exclude that field/prop from serializaion or write a custom formatter for it."); }
/// <summary> /// Tries to create the service with the specified constructor using the specified parameters. /// <para /> /// This method will not throw an exception when the invocation fails. /// </summary> /// <param name="typeToConstruct">Type of the service.</param> /// <param name="constructor">The constructor info.</param> /// <param name="tag">The preferred tag when resolving dependencies.</param> /// <param name="parameters">The parameters to pass into the constructor.</param> /// <param name="checkConstructor">if set to <c>true</c>, check whether the constructor can be used before using it.</param> /// <param name="hasMoreConstructorsLeft">if set to <c>true</c>, more constructors are left so don't throw exceptions.</param> /// <param name="typeMetaData">Metadata about type beiing constructed.</param> /// <returns>The instantiated service or <c>null</c> if the instantiation fails.</returns> /// <remarks>Note that this method does not require an implementation of /// <see cref="TypeRequestPath" /> because this already has the parameter values /// and thus cannot lead to invalid circular dependencies.</remarks> private object TryCreateToConstruct(Type typeToConstruct, ConstructorInfo constructor, object tag, object[] parameters, bool checkConstructor, bool hasMoreConstructorsLeft, TypeMetaData typeMetaData) { // Check if this constructor is even possible if (checkConstructor) { if (!CanConstructorBeUsed(constructor, tag, true, parameters)) { return(null); } } try { var finalParameters = new List <object>(parameters); var ctorParameters = constructor.GetParameters(); for (int i = parameters.Length; i < ctorParameters.Length; i++) { object ctorParameterValue; if (tag != null && _serviceLocator.IsTypeRegistered(ctorParameters[i].ParameterType, tag)) { // Use preferred tag ctorParameterValue = _serviceLocator.ResolveType(ctorParameters[i].ParameterType, tag); } else { // No tag or fallback to default without tag ctorParameterValue = _serviceLocator.ResolveType(ctorParameters[i].ParameterType); } finalParameters.Add(ctorParameterValue); } var finalParametersArray = finalParameters.ToArray(); Log.Debug("Calling constructor.Invoke with the right parameters"); var instance = constructor.Invoke(finalParametersArray); InitializeAfterConstruction(instance, typeMetaData); return(instance); } #if NET || NETSTANDARD catch (MissingMethodException) { // Ignore, we accept this } #endif catch (TargetParameterCountException) { // Ignore, we accept this } catch (CircularDependencyException) { // Only handle CircularDependencyExceptions we throw ourselves because we support generic types such as // Dictionary<TKey, TValue> which has a constructor with IDictionary<TKey, TValue> if (!hasMoreConstructorsLeft) //if (string.Equals(TypeRequestPathName, ex.TypePath.Name, StringComparison.Ordinal)) { throw; } } catch (Exception ex) { // Real exceptions bubble up, otherwise return null Log.Error(ex, "Failed to instantiate type '{0}', but this was an unexpected error", typeToConstruct.FullName); throw; } // Some loging like .GetSignature are expensive var logDebug = LogManager.LogInfo.IsDebugEnabled && !LogManager.LogInfo.IgnoreCatelLogging; if (logDebug) { Log.Debug("Failed to create instance using dependency injection for type '{0}' using constructor '{1}'", typeToConstruct.FullName, constructor.GetSignature()); } return(null); }
//Factory function for networked entities public INetworkable EntityFactory(TypeMetaData metaData, in ObjectHandle handle)
private static string ConvertToJson(TypeMetaData metaData) { return(JsonSerializer.ConvertToJson(metaData)); }
/// <summary> /// Tries to create the service with the specified constructor using the specified parameters. /// <para /> /// This method will not throw an exception when the invocation fails. /// </summary> /// <param name="typeToConstruct">Type of the service.</param> /// <param name="constructor">The constructor info.</param> /// <param name="tag">The preferred tag when resolving dependencies.</param> /// <param name="parameters">The parameters to pass into the constructor.</param> /// <param name="checkConstructor">if set to <c>true</c>, check whether the constructor can be used before using it.</param> /// <param name="hasMoreConstructorsLeft">if set to <c>true</c>, more constructors are left so don't throw exceptions.</param> /// <param name="typeMetaData">Metadata about type beiing constructed.</param> /// <returns>The instantiated service or <c>null</c> if the instantiation fails.</returns> /// <remarks>Note that this method does not require an implementation of /// <see cref="TypeRequestPath" /> because this already has the parameter values /// and thus cannot lead to invalid circular dependencies.</remarks> private object TryCreateToConstruct(Type typeToConstruct, ConstructorInfo constructor, object tag, object[] parameters, bool checkConstructor, bool hasMoreConstructorsLeft, TypeMetaData typeMetaData) { // Check if this constructor is even possible if (checkConstructor) { if (!CanConstructorBeUsed(constructor, tag, true, parameters)) { return(null); } } try { var finalParameters = new List <object>(parameters); var ctorParameters = constructor.GetParameters(); for (var i = parameters.Length; i < ctorParameters.Length; i++) { object ctorParameterValue = null; var parameterTypeToResolve = ctorParameters[i].ParameterType; if (!typeof(string).IsAssignableFromEx(parameterTypeToResolve) && typeof(IEnumerable).IsAssignableFromEx(parameterTypeToResolve)) { var collectionElementType = parameterTypeToResolve.GetCollectionElementType(); if (collectionElementType != null && _serviceLocator.IsTypeRegisteredWithOrWithoutTag(collectionElementType)) { var ctorParameterValueLocal = _serviceLocator.ResolveTypes(collectionElementType).Cast(collectionElementType); if (parameterTypeToResolve.IsArray) { ctorParameterValueLocal = ctorParameterValueLocal.ToSystemArray(collectionElementType); } else if (typeof(IReadOnlyList <>).MakeGenericType(collectionElementType).IsAssignableFromEx(parameterTypeToResolve) || typeof(IReadOnlyCollection <>).MakeGenericType(collectionElementType).IsAssignableFromEx(parameterTypeToResolve)) { ctorParameterValueLocal = ctorParameterValueLocal.AsReadOnly(collectionElementType); } else if (typeof(IList <>).MakeGenericType(collectionElementType).IsAssignableFromEx(parameterTypeToResolve) || typeof(ICollection <>).MakeGenericType(collectionElementType).IsAssignableFromEx(parameterTypeToResolve)) { ctorParameterValueLocal = ctorParameterValueLocal.ToList(collectionElementType); } ctorParameterValue = ctorParameterValueLocal; } } if (ctorParameterValue is null) { if (!(tag is null) && _serviceLocator.IsTypeRegistered(parameterTypeToResolve, tag)) { // Use preferred tag ctorParameterValue = _serviceLocator.ResolveType(parameterTypeToResolve, tag); } else { // No tag or fallback to default without tag ctorParameterValue = _serviceLocator.ResolveType(parameterTypeToResolve); } } finalParameters.Add(ctorParameterValue); } var finalParametersArray = finalParameters.ToArray(); //Log.Debug("Calling constructor.Invoke with the right parameters"); var instance = constructor.Invoke(finalParametersArray); InitializeAfterConstruction(instance, typeMetaData); return(instance); }
public AssemblyFormatterGenerator(CerasSerializer ceras, Type type) { _ceras = ceras; _type = type; _meta = _ceras.GetTypeMetaData(_type); }
/// <summary> /// Initializes a new instance of the <see cref="EditableAdapter<TWrappedObject>"/> class. /// </summary> /// <param name="current">The object being wrapped.</param> public EditableAdapter(TWrappedObject current) { _changedProperties = new Dictionary <PropertyInfo, object>(); _current = current; _metaData = TypeMetaDataRepository.GetFor(this.GetType(), typeof(TWrappedObject)); }
public Member(MemberInfo info, TypeMetaData metaData, ITypeConverter typeConverter, in BitConverterOptions converterOptions, int?changeNotificationIndex)