public void CanApplyConstructorArgsToAbstractType() { IResource resource = new ReadOnlyXmlTestResource("ctor-args.xml", GetType()); XmlObjectFactory xof = new XmlObjectFactory(resource); TestObject rod = (TestObject)xof.GetObject("rod"); Assert.AreEqual(1, rod.Age); RootObjectDefinition def = (RootObjectDefinition) xof.GetObjectDefinition("rod"); ConstructorResolver resolver = new ConstructorResolver(xof, xof, new SimpleInstantiationStrategy(), new ObjectDefinitionValueResolver(xof)); ConstructorInstantiationInfo ci = resolver.GetConstructorInstantiationInfo("rod", def, null, null); AbstractObjectDefinition objDef = (AbstractObjectDefinition)xof.GetObjectDefinition("foo"); objDef.IsAbstract = false; TestObject foo = (TestObject) xof.GetObject("foo"); Assert.AreEqual(2, foo.Age); }
/// <summary> /// "autowire constructor" (with constructor arguments by type) behaviour. /// </summary> /// <param name="name">The name of the object to autowire by type.</param> /// <param name="definition">The object definition to update through autowiring.</param> /// <param name="ctors">The chosen candidate constructors.</param> /// <param name="explicitArgs">The argument values passed in programmatically via the GetObject method, /// or <code>null</code> if none (-> use constructor argument values from object definition)</param> /// <returns> /// An <see cref="Spring.Objects.IObjectWrapper"/> for the new instance. /// </returns> /// <remarks> /// <para> /// Also applied if explicit constructor argument values are specified, /// matching all remaining arguments with objects from the object factory. /// </para> /// <para> /// This corresponds to constructor injection: in this mode, a Spring.NET /// object factory is able to host components that expect constructor-based /// dependency resolution. /// </para> /// </remarks> protected IObjectWrapper AutowireConstructor(string name, RootObjectDefinition definition, ConstructorInfo[] ctors, object[] explicitArgs) { ConstructorResolver constructorResolver = new ConstructorResolver(this, this, InstantiationStrategy, CreateValueResolver()); return constructorResolver.AutowireConstructor(name, definition, ctors, explicitArgs); }
/// <summary> /// Instantiate an object instance using a named factory method. /// </summary> /// <remarks> /// <p> /// The method may be static, if the <paramref name="definition"/> /// parameter specifies a class, rather than a /// <see cref="Spring.Objects.Factory.IFactoryObject"/> instance, or an /// instance variable on a factory object itself configured using Dependency /// Injection. /// </p> /// <p> /// Implementation requires iterating over the static or instance methods /// with the name specified in the supplied <paramref name="definition"/> /// (the method may be overloaded) and trying to match with the parameters. /// We don't have the types attached to constructor args, so trial and error /// is the only way to go here. /// </p> /// </remarks> /// <param name="name"> /// The name associated with the supplied <paramref name="definition"/>. /// </param> /// <param name="definition"> /// The definition describing the instance that is to be instantiated. /// </param> /// <param name="arguments"> /// Any arguments to the factory method that is to be invoked. /// </param> /// <returns> /// The result of the factory method invocation (the instance). /// </returns> protected virtual IObjectWrapper InstantiateUsingFactoryMethod(string name, RootObjectDefinition definition, object[] arguments) { ConstructorResolver constructorResolver = new ConstructorResolver(this, this, InstantiationStrategy, CreateValueResolver()); return constructorResolver.InstantiateUsingFactoryMethod(name, definition, arguments); }
/// <summary> /// Applies attributes to the proxy class. /// </summary> /// <param name="typeBuilder">The type builder to use.</param> /// <param name="targetType">The proxied class.</param> /// <see cref="IProxyTypeBuilder.ProxyTargetAttributes"/> /// <see cref="IProxyTypeBuilder.TypeAttributes"/> protected override void ApplyTypeAttributes(TypeBuilder typeBuilder, Type targetType) { foreach (object attr in GetTypeAttributes(targetType)) { if (attr is CustomAttributeBuilder) { typeBuilder.SetCustomAttribute((CustomAttributeBuilder)attr); } #if NET_2_0 else if (attr is CustomAttributeData) { typeBuilder.SetCustomAttribute( ReflectionUtils.CreateCustomAttribute((CustomAttributeData)attr)); } #endif else if (attr is Attribute) { typeBuilder.SetCustomAttribute( ReflectionUtils.CreateCustomAttribute((Attribute)attr)); } else if (attr is IObjectDefinition) { RootObjectDefinition objectDefinition = (RootObjectDefinition) attr; //TODO check that object definition is for an Attribute type. //Change object definition so it can be instantiated and make prototype scope. objectDefinition.IsAbstract = false; objectDefinition.IsSingleton = false; string objectName = ObjectDefinitionReaderUtils.GenerateObjectName(objectDefinition, objectFactory); objectFactory.RegisterObjectDefinition(objectName, objectDefinition); //find constructor and constructor arg values to create this attribute. ConstructorResolver constructorResolver = new ConstructorResolver(objectFactory, objectFactory, new SimpleInstantiationStrategy(), new ObjectDefinitionValueResolver(objectFactory)); ConstructorInstantiationInfo ci = constructorResolver.GetConstructorInstantiationInfo(objectName, objectDefinition, null, null); if (objectDefinition.PropertyValues.PropertyValues.Length == 0) { CustomAttributeBuilder cab = new CustomAttributeBuilder(ci.ConstructorInfo, ci.ArgInstances); typeBuilder.SetCustomAttribute(cab); } else { object attributeInstance = objectFactory.GetObject(objectName); IObjectWrapper wrappedAttributeInstance = new ObjectWrapper(attributeInstance); PropertyInfo[] namedProperties = wrappedAttributeInstance.GetPropertyInfos(); object[] propertyValues = new object[namedProperties.Length]; for (int i = 0; i < namedProperties.Length; i++) { propertyValues[i] = wrappedAttributeInstance.GetPropertyValue(namedProperties[i].Name); } CustomAttributeBuilder cab = new CustomAttributeBuilder(ci.ConstructorInfo, ci.ArgInstances, namedProperties, propertyValues); typeBuilder.SetCustomAttribute(cab); } } } }